数据库准备
# 1 表结构 CREATE TABLE `t01_user` ( `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `user_name` varchar(20) DEFAULT NULL COMMENT '姓名', `credits` varchar(11) DEFAULT NULL COMMENT '积分', `password` varchar(11) DEFAULT NULL COMMENT '密码', `last_visit` datetime DEFAULT NULL COMMENT '最后一次登陆时间', `last_ip` varchar(11) DEFAULT NULL COMMENT '最后一次登陆ip', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='t01模块的用户表' ; CREATE TABLE `t01_login_log` ( `login_log_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `user_id` int(11) NOT NULL COMMENT 't01_user 用户表主键', `ip` varchar(20) NOT NULL COMMENT 'ip', `login_datetime` datetime NOT NULL COMMENT '登陆时间', PRIMARY KEY (`login_log_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ; # 2 表数据 INSERT INTO t01_user (user_name,password) VALUES('admin','123456') ;
依赖准备
group 'bbt' version '1.0-SNAPSHOT' apply plugin: 'java' apply plugin: 'jetty' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { // https://mvnrepository.com/artifact/org.springframework/spring-core compile group: 'org.springframework', name: 'spring-core', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/org.springframework/spring-context compile group: 'org.springframework', name: 'spring-context', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/org.springframework/spring-test compile group: 'org.springframework', name: 'spring-test', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/org.springframework/spring-web compile group: 'org.springframework', name: 'spring-web', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/org.springframework/spring-webmvc compile group: 'org.springframework', name: 'spring-webmvc', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/org.springframework/spring-jdbc compile group: 'org.springframework', name: 'spring-jdbc', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/org.springframework/spring-aop compile group: 'org.springframework', name: 'spring-aop', version: '3.2.17.RELEASE' // https://mvnrepository.com/artifact/mysql/mysql-connector-java compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.39' // https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4' // https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api compile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.0-b01' // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4' // https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.2' // https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils compile group: 'commons-beanutils', name: 'commons-beanutils', version: '1.9.2' // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.1' // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.1' // https://mvnrepository.com/artifact/jstl/jstl compile group: 'jstl', name: 'jstl', version: '1.2' testCompile group: 'junit', name: 'junit', version: '4.12' }
日志:log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration status="OFF"> <!--appenders配置输出到什么地方--> <appenders> <!--Console:控制台--> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </appenders> <loggers> <!--additivity默认为true,为输出两遍日志--> <logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG" additivity="false"> <appender-ref ref="Console"/> </logger> <!--建立一个默认的root的logger--> <root level="trace"> <appender-ref ref="Console"/> </root> </loggers> </configuration>
领域对象
package org.zln.bbt.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import java.util.Date; /** * Created by sherry on 16/7/1. * 用户领域对象 */ public class User { private int userId; private String userName; private String password; //当前积分 private int credits; //最后一次登陆用户的ip private String lastIp; //最后一次登陆的时间 private Date lastVisit; @Override public String toString() { return new ToStringBuilder(this) .append("userId", userId) .append("userName", userName) .append("password", password) .append("credits", credits) .append("lastIp", lastIp) .append("lastVisit", lastVisit) .toString(); } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getCredits() { return credits; } public void setCredits(int credits) { this.credits = credits; } public String getLastIp() { return lastIp; } public void setLastIp(String lastIp) { this.lastIp = lastIp; } public Date getLastVisit() { return lastVisit; } public void setLastVisit(Date lastVisit) { this.lastVisit = lastVisit; } }
package org.zln.bbt.domain; import org.apache.commons.lang3.builder.ToStringBuilder; import java.util.Date; /** * Created by sherry on 16/7/1. * 登陆日志领域对象 */ public class LoginLog { //登陆日志主键 private int loginLogId; //登陆用户主键 private int userId; //登陆用户ip private String ip; //登陆时间 private Date loginDate; @Override public String toString() { return new ToStringBuilder(this) .append("loginLogId", loginLogId) .append("userId", userId) .append("ip", ip) .append("loginDate", loginDate) .toString(); } public int getLoginLogId() { return loginLogId; } public void setLoginLogId(int loginLogId) { this.loginLogId = loginLogId; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Date getLoginDate() { return loginDate; } public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } }
Dao代码
package org.zln.bbt.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.stereotype.Repository; import org.zln.bbt.domain.User; import java.sql.ResultSet; import java.sql.SQLException; import static java.sql.Types.VARCHAR; /** * Created by sherry on 16/7/1. * 用户Dao类 */ @Repository("userDao") public class UserDao { @Autowired @Qualifier("jdbcTemplate") private JdbcTemplate jdbcTemplate; /** * 获取匹配的记录数 * @param username 用户名 * @param password 密码 * @return 记录数 */ public int getMatchCount(String username,String password){ final String sqlStr = " SELECT count(1) FROM t_user WHERE user_name = ? AND password = ? "; int count = jdbcTemplate.queryForInt(sqlStr,new Object[]{username,password},new int[]{VARCHAR, VARCHAR}); return count; } /** * 根据用户名查找用户 * @param username 用户名 * @return 用户 */ public User findUserByUserName(final String username){ final String sqlStr = " SELECT user_id,user_name,credits FROM t_user WHERE user_name = ? "; final User user = new User(); jdbcTemplate.query(sqlStr, new Object[]{user}, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { user.setUserId(rs.getInt("user_id")); user.setUserName(rs.getString("user_name")); user.setCredits(rs.getInt("credits")); } }); return user; } /** * 更新用户信息 * @param user */ public void updateLoginInfo(User user){ final String sqlStr = " UPDATE t_user SET last_visit = ?,last_ip = ?,credits = ? WHERE user_id = ? "; jdbcTemplate.update(sqlStr,new Object[]{user.getLastVisit(),user.getLastIp(),user.getCredits(),user.getUserId()}); } }
package org.zln.bbt.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.zln.bbt.domain.LoginLog; /** * Created by sherry on 16/7/1. * 登陆日志Dao类 */ public class LoginLogDao { @Autowired @Qualifier("jdbcTemplate") private JdbcTemplate jdbcTemplate; /** * 新增登陆日志 * @param loginLog 日志对象 */ public void insertLoginLog(LoginLog loginLog){ final String sqlStr = " INSERT INTO t_login_log (user_id,ip,login_datetime) VALUES (?,?,?) "; jdbcTemplate.update(sqlStr,new Object[]{loginLog.getUserId(),loginLog.getIp(),loginLog.getLoginDate()}); } }
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!--这个包下的,所有加过特殊注解的类,都被Spring管理--> <context:component-scan base-package="org.zln.bbt"/> <!--开启注解注入--> <context:annotation-config/> <!--配置数据源--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/zln?useSSL=false" p:username="root" p:password="123456"/> <!--JDBC模板类--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource"/> <!--事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/> <!--使用注解配置事务--> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
Service
package org.zln.bbt.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.zln.bbt.dao.LoginLogDao; import org.zln.bbt.dao.UserDao; import org.zln.bbt.domain.LoginLog; import org.zln.bbt.domain.User; /** * Created by sherry on 16/7/1. * 用户业务层 */ @Service("userService") public class UserService { @Autowired private UserDao userDao; @Autowired private LoginLogDao loginLogDao; public boolean hasMatchUser(String username,String password){ return userDao.getMatchCount(username,password)>0; } public User findUserByUserName(String username){ return userDao.findUserByUserName(username); } public void loginSuccess(User user){ user.setCredits(user.getCredits()+5); LoginLog loginLog = new LoginLog(); loginLog.setIp(user.getLastIp()); loginLog.setLoginDate(user.getLastVisit()); userDao.updateLoginInfo(user); loginLogDao.insertLoginLog(loginLog); } }
测试
package org.zln.bbt.service; import org.junit.Test; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.zln.bbt.domain.User; import java.util.Date; import static org.junit.Assert.*; /** * Created by sherry on 16/7/1. */ @RunWith(SpringJUnit4ClassRunner.class)//基于Junit4的Spring测试框架 @ContextConfiguration(locations = {"/applicationContext.xml"}) public class UserServiceTest { private Logger logger = LogManager.getLogger(UserServiceTest.class); @Autowired private UserService userService; @Test public void testHasMatchUser() throws Exception { boolean b1 = userService.hasMatchUser("admin","123456"); boolean b2 = userService.hasMatchUser("admin","111"); logger.info(b1); logger.info(b2); assertTrue(b1); assertTrue(!b2); } @Test public void testFindUserByUserName() throws Exception { User user = userService.findUserByUserName("admin"); assertEquals("admin",user.getUserName()); } @Test public void testLoginSuccess() throws Exception { User user = userService.findUserByUserName("admin"); user.setLastVisit(new Date()); userService.loginSuccess(user); } }
Action
package org.zln.bbt.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import org.zln.bbt.command.LoginCommand; import org.zln.bbt.domain.User; import org.zln.bbt.service.UserService; import javax.servlet.http.HttpServletRequest; import java.util.Date; /** * Created by sherry on 16/7/4. */ @Controller public class LoginController { @Autowired @Qualifier("userService") private UserService userService; @RequestMapping(value = "/index.html") public String loginPage(){ return "login"; } @RequestMapping(value = "/loginCheck.html") public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){ boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(),loginCommand.getPassword()); if (!isValidUser){ return new ModelAndView("login","error","用户名或密码错误"); }else { User user = userService.findUserByUserName(loginCommand.getUserName()); user.setLastIp(request.getRemoteAddr()); user.setLastVisit(new Date()); userService.loginSuccess(user); request.getSession().setAttribute("user",user); return new ModelAndView("main"); } } }
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--① 启动Spring--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml</param-value> </context-param> <!--② 启动Spring容器的监听,引用①处的上下文参数获取Spring配置文件地址--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--③ 配置Spring MVC地址映射--> <servlet> <servlet-name>bbt</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>bbt</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app>
bbt-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!--这个包下的,所有加过特殊注解的类,都被Spring管理--> <context:component-scan base-package="org.zln" resource-pattern="**/*Controller.class"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/> </beans>
WEB-INF/jsp/login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <% String homePage = request.getContextPath(); %> <html> <head> <title>宝宝淘论坛登陆</title> </head> <body> <c:if test="${!empty error}"> <font color="red"><c:out value="${error}"/></font> </c:if> <form action="<%=homePage%>/loginCheck.html" method="post"> <table> <tr> <td>用户名</td> <td> <input type="text" name="userName"> </td> </tr> <tr> <td>密码</td> <td> <input type="password" name="password"> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="登陆"> <input type="submit" value="重置"> </td> </tr> </table> </form> </body> </html>
WEB-INF/jsp/main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <% String homePage = request.getContextPath(); %> <html> <head> <title>宝宝淘论坛</title> </head> <body> ${user.userName},欢迎登陆,当前积分:${user.credits}<br/> </body> </html>