系统概述:
2015年5月8日 14:05:49
本系统为一个常规的用户登录系统,主要完成了用户登录界面设计、用户登录后信息校验、更新用户登录信息以及记录用户登录信息等。
整个系统以Spring框架为基础来实现,项目构架时进行了分层设计,主要包括:持久层、业务层、控制层以及POJO(demain);
本系统使用的技术为:
1. 数据库:MySQL;
1. 使用 JdbcTemplate 实现Mysql数据库的增、删、改、查操作;
8. 配置Spring MVC:(web.xml)
9. Spring声明式事务;
项目整体布局:
![]()
![]()
![]()
下面是配置文件及前端界面等;
![]()
上述指令执行完成后,在Mysql创建的情况如下:![]()
![]()
说明:
说明:
applicationContext.xml
说明:
说明:
说明:
![]()
![]()
![]()
![]()
![]()
com.baobaotao.service包:TestUserService.java
![]()
![]()
2. 数据库操作:Spring jdbc;
3. MVC框架,Spring MVC;
4. 容器:Spring容器;
涉及到的技术点:
1. 使用 JdbcTemplate 实现Mysql数据库的增、删、改、查操作;
2. 注解的使用:
@Repository:注解持久层(dao)bean;
@Service:注解业务层bean;
@Controller:展现层(控制层)bean,标注为Spring mvc的控制器;
@Autowired:将Spring容器中的bean注入进来;
@ContextConfiguration:指定Spring配置文件的位置;
@RequestMapping:指定如何映射请求地址;
3. RowCallbackHandler:查询结果处理的回调接口,实现ResultSet到POJO对象的转换;
4. 事务管理器:为数据库操作实现事务;
5. 引入shema命名空间:
p: 用于简化类的成员变量;
tx:
aop:
6. 利用junit进行测试;
7. 配置Spring容器:配置Spring容器所必须的两个参数(web.xml)
<!-- 从类路径下加载Spring配置文件,classpath关键字特指从类路径下加载 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><!-- 负责启动Spring容器的监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
8. 配置Spring MVC:(web.xml)
<!-- 配置Spring MVC,其对应的配置文件为:servlet-name-servlet.xml,本项目的为:baobaotao-servlet.xml --><servlet><servlet-name>baobaotao</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>3</load-on-startup></servlet><servlet-mapping><servlet-name>baobaotao</servlet-name><url-pattern>*.html</url-pattern></servlet-mapping>
9. Spring声明式事务;
这个以后在具体介绍。
项目整体布局
项目整体布局:
主要包括src和test,其中test为junit测试类,主要用于测试业务层;
使用的jar包



下面是配置文件及前端界面等;

Mysql数据库指令
DROP DATABASE IF EXISTS sampledb;CREATE DATABASE sampledb DEFAULT CHARACTER SET utf8;USE sampledb;##创建用户表CREATE TABLE t_user (user_id INT AUTO_INCREMENT PRIMARY KEY,user_name VARCHAR(30),credits INT,password VARCHAR(32),last_visit datetime,last_ip VARCHAR(23))ENGINE=InnoDB;##创建用户登录日志表CREATE TABLE t_login_log (login_log_id INT AUTO_INCREMENT PRIMARY KEY,user_id INT,ip VARCHAR(23),login_datetime datetime)ENGINE=InnoDB;##插入初始化数据INSERT INTO t_user (user_name,password)VALUES('admin','123456');COMMIT;


源程序
com.baobaotao.domain包:定义POJO对象
LoginLog.java
package com.baobaotao.domain;import java.io.Serializable;import java.util.Date;public class LoginLog implements Serializable{private int loginLogId;private int userId;private String ip;private Date loginDate;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;}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;}}
User.java
package com.baobaotao.domain;import java.io.Serializable;import java.util.Date;public class User implements Serializable{private int userId;private String userName;private String password;private int credits;private String lastIp;private Date lastVisit;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;}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;}}
com.baobaotao.dao包
LoginLogDao.java
package com.baobaotao.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;import com.baobaotao.domain.LoginLog;@Repositorypublic class LoginLogDao {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 插入登录信息* @param loginLog*/public void insertLoginLog(LoginLog loginLog) {String sqlStr = "INSERT INTO t_login_log(user_id,ip,login_datetime) "+ "VALUES(?,?,?)";Object[] args = { loginLog.getUserId(), loginLog.getIp(),loginLog.getLoginDate() };jdbcTemplate.update(sqlStr, args);}}
UserDao.java
package com.baobaotao.dao;import java.sql.ResultSet;import java.sql.SQLException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowCallbackHandler;import org.springframework.stereotype.Repository;import com.baobaotao.domain.User;@Repositorypublic class UserDao {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 获取匹配的用户数量* @param userName* @param password* @return*/public int getMatchCount(String userName, String password) {String sqlStr = " SELECT count(*) FROM t_user "+ " WHERE user_name =? and password=? ";return jdbcTemplate.queryForInt(sqlStr, new Object[] { userName, password });}/*** 查询用户* @param userName* @return*/public User findUserByUserName(final String userName) {String sqlStr = " SELECT user_id,user_name,credits "+ " FROM t_user WHERE user_name =? ";final User user = new User();jdbcTemplate.query(sqlStr, new Object[] { userName },new RowCallbackHandler() {public void processRow(ResultSet rs) throws SQLException {user.setUserId(rs.getInt("user_id"));user.setUserName(userName);user.setCredits(rs.getInt("credits"));}});return user;}/*** 更新登录信息* @param user*/public void updateLoginInfo(User user) {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()});}}
com.baobaotao.service包
UserService.java
package com.baobaotao.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.baobaotao.dao.LoginLogDao;import com.baobaotao.dao.UserDao;import com.baobaotao.domain.LoginLog;import com.baobaotao.domain.User;@Servicepublic class UserService {@Autowiredprivate UserDao userDao;@Autowiredprivate LoginLogDao loginLogDao;/*** 是否有匹配的用户* @param userName* @param password* @return*/public boolean hasMatchUser(String userName, String password) {int matchCount =userDao.getMatchCount(userName, password);return matchCount > 0;}/*** 根据用户名查找用户* @param userName* @return*/public User findUserByUserName(String userName) {return userDao.findUserByUserName(userName);}/*** 登录成功时,更新登录信息并添加登录记录* @param user*/public void loginSuccess(User user) {user.setCredits( 5 + user.getCredits()); //信用加5LoginLog loginLog = new LoginLog();loginLog.setUserId(user.getUserId());loginLog.setIp(user.getLastIp());loginLog.setLoginDate(user.getLastVisit());userDao.updateLoginInfo(user);loginLogDao.insertLoginLog(loginLog);}}
com.baobaotao.web包
LoginCommand.java
package com.baobaotao.web;public class LoginCommand {private String userName;private String password;public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}}
LoginController.java
package com.baobaotao.web;import java.util.Date;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import com.baobaotao.domain.User;import com.baobaotao.service.UserService;@Controllerpublic class LoginController{@Autowiredprivate 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.getLocalAddr());user.setLastVisit(new Date());userService.loginSuccess(user);request.getSession().setAttribute("user", user);return new ModelAndView("main");}}}
说明:
在mvc架构中,model和view是松耦合的,控制层负责产生model数据,而view负责渲染模型数据。
request.getSession().setAttribute("user", user);
return new ModelAndView("main");
等价于:
ModelAndView("main", "user", user);
web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><!-- 从类路径下加载Spring配置文件,classpath关键字特指从类路径下加载 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><!-- 负责启动Spring容器的监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 配置Spring MVC,其对应的配置文件为:servlet-name-servlet.xml,本项目的为:baobaotao-servlet.xml --><servlet><servlet-name>baobaotao</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>3</load-on-startup></servlet><servlet-mapping><servlet-name>baobaotao</servlet-name><url-pattern>*.html</url-pattern></servlet-mapping></web-app>
说明:
web.xml中,contextConfigLocation和ContextLoaderListener是使用Spring容器必须配置的;
而DispatcherServlet是使用Spring MVC所必须的。
Spring配置文件
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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 --><context:component-scan base-package="com.baobaotao.dao"/><context:component-scan base-package="com.baobaotao.service"/><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"p:driverClassName="com.mysql.jdbc.Driver"p:url="jdbc:mysql://localhost:3306/sampledb"p:username="root"p:password="xxx" /><!-- 配置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" /><!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务 --><aop:config proxy-target-class="true"><aop:pointcut id="serviceMethod"expression=" execution(* com.baobaotao.service..*(..))" /><aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" /></aop:config><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" /></tx:attributes></tx:advice></beans>
说明:
上述配置文件中,使用了schema来简化配置。如:<p:...>、<tx:...>、<aop:...>;
组件扫描:<context:component>扫描标记了@Controller、@Service、@Repository的类,自动为这些类创建bean。
Spring MVC配置文件
baobaotao-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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 扫描web包,应用Spring的注解 --><context:component-scan base-package="com.baobaotao.web"/><!-- 配置视图解析器,将ModelAndView及字符串解析为具体的页面 --><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"p:viewClass="org.springframework.web.servlet.view.JstlView"p:prefix="/WEB-INF/jsp/"p:suffix=".jsp" /></beans>
说明:
这是配置了InternalResourceViewResolver视图解析器。Spring MVC中的视图解析器有好多种,且每种视图解析器都可以设置优先级。InternalResourceViewResolver视图解析器只是最常用且最普通的一种视图解析器,它的默认优先级是最低的。
前端jsp界面
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><html><head><title>论坛登录</title></head><body><c:if test="${!empty error}"><font color="red"><c:out value="${error}" /></font></c:if><form action="<c:url value="loginCheck.html"/>" method="post">用户名:<input type="text" name="userName"><br>密 码:<input type="password" name="password"><br><input type="submit" value="登录" /><input type="reset" value="重置" /></form></body></html>
说明:
这里使用了jstl标签,<c:url value="loginCheck.html"/>的jstl标签会在url前自动加上应用程序的部署根目录,假设应用程序部署在bbt目录下,<c:url/>标签将输出:/bbt/loginCheck.html 。通过<c:url />标签,很好的解决了开发和应用部署目录不一致的问题。
main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>论坛</title></head><body>${user.userName},欢迎您进入宝宝淘论坛,您当前积分为${user.credits};</body></html>
log4j.properties
log4j.rootLogger=DEBUG,A1log4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout=org.apache.log4j.PatternLayoutlog4j.appender.A1.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n
用户名密码输入错误时:

用户名密码输入正确时:


下面是数据库信息:


Junit测试
com.baobaotao.service包:TestUserService.java
package com.baobaotao.service;import static org.junit.Assert.*;import java.util.Date;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 com.baobaotao.domain.User;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:applicationContext.xml"})public class TestUserService {@Autowiredprivate UserService userService;@Testpublic void testHasMatchUser() {boolean b1 = userService.hasMatchUser("admin", "123456");boolean b2 = userService.hasMatchUser("admin", "1111");assertTrue(b1);assertTrue(!b2);}@Testpublic void testFindUserByUserName() {User user = userService.findUserByUserName("admin");assertEquals(user.getUserName(), "admin");}@Testpublic void testAddLoginLog() {User user = userService.findUserByUserName("admin");user.setUserId(1);user.setUserName("admin");user.setLastIp("192.168.12.7");user.setLastVisit(new Date());userService.loginSuccess(user);}}

测试结果如下:

至此,整个系统全部完成。
附件列表
转载请标明出处:http://www.cnblogs.com/ssslinppp/

浙公网安备 33010602011771号