实例名:小春论坛
实例功能:
登录界面给出一个有用户名/密码的输入表单,用户填写并提交表单后,服务器端程序检查是否有匹配的用户名/密码。若有,则记录用户的成功登录日志,更新用户最后登录时间和IP,并给该用户增加5个积分,然后重定向到欢迎页面。
Maven:apache-maven-3.3.9(本人自己的版本,与书中不一致)
MySql::mysql 8.0.12(本人自己的版本,与书中不一致)
IDE:IDEA2018.1 64位
建表语句:
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),
password VARCHAR(32),
credits INT,
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;
其中t_user为用户信息表,t_login_log为用户登录日志表。ENGINE=InnoDB; 指定表的引擎为InnoDB类型,该类型的表支持事务。并且插入了一条用户数据:admin/123456,方便之后进行登录操作。
IDEA编码设置为UTF-8编码:
File-->Setting-->打开如下页面设置
File-->Other Setting-->Default Setting-->打开如下设置(为IDE设置默认属性)
创建Maven工程步骤:
File-->New-->Project-->
点击结束完成Maven项目创建(注意,在这之前要安装好Maven环境,并且在IDEA中配置你的Maven,具体方法自行百度)
初始工程文件结构:
完整的项目目录结构:
建议读者先按完整项目目录结构建好文件,然后跟着我后面贴的代码及注释完成项目
新建文件时注意webapp的创建过程:
选择文件结构选项卡:
添加本项目模块:
添加web原型:
修改成下面的路径:
骨架搭好了接下来就要剩下把内容填充上了
pom.xml
4.0.0
com.smart
chapter2
1.0
Spring4.x第二章实例
Spring4.x第二章实例
war
UTF-8
4.2.1.RELEASE
8.0.12
2.5
org.springframework
spring-core
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-aop
${spring.version}
org.springframework
spring-aspects
${spring.version}
mysql
mysql-connector-java
${mysql.version}
commons-dbcp
commons-dbcp
1.4
javax.servlet
servlet-api
${servlet.version}
javax.servlet
jstl
1.2
org.springframework
spring-context
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-test
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.testng
testng
6.9.9
test
org.mortbay.jetty
maven-jetty-plugin
6.1.25
8000
60000
/bbs
0
pom中配置了jetty插件,所以不必再手动部署配置tomcat服务器,项目完成编写后直接点击maven projects选项卡的jetty插件下的jetty:run运行即可。注意,mysql版本要设置成你自己的版本
smart-context.xml 将数据库用户名密码改成你自己的
log4j.properties
log4j.rootLogger=DEBUG,A1
log4j.logger.org.springframework=debug
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n
smart-servlet.xml
web.xml
contextConfigLocation
classpath:smart-context.xml
org.springframework.web.context.ContextLoaderListener
smart
org.springframework.web.servlet.DispatcherServlet
2
smart
*.html
UserDao.java
package com.smart.dao;
import com.smart.domain.User;
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 java.sql.ResultSet;
import java.sql.SQLException;
@Repository
public class UserDao {
private JdbcTemplate jdbcTemplate;
private final static String MATCH_COUNT_SQL=" SELECT COUNT(*) FROM t_user "+
" WHERE user_name=? AND password=? ";
private final static String UPDATE_LOGIN_INFO_SQL=" UPDATE t_user SET "
+" last_visit=?,last_ip=?,credits=? WHERE user_id=? ";
private final static String FIND_USER_BY_NAME_SQL=" SELECT * from t_user where user_name=? ";
@Autowired
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate=jdbcTemplate;
}
public int getMatchCount(String userName,String password){
return jdbcTemplate.queryForObject(MATCH_COUNT_SQL,new Object[]{userName,password},Integer.class);
}
public User findUserByUserName(final String userName){
final User user=new User();
jdbcTemplate.query(FIND_USER_BY_NAME_SQL, new RowCallbackHandler() {//回调接口
public void processRow(ResultSet resultSet) throws SQLException {
user.setUserId(resultSet.getInt("user_id"));
user.setUserName(resultSet.getString("user_name"));
user.setCredits(resultSet.getInt("credits"));
user.setLastVisit(resultSet.getTimestamp("last_visit"));
user.setLastIp(resultSet.getString("last_ip"));
}
},userName);
return user;
}
public void updateLoginInfo(User user){
jdbcTemplate.update(UPDATE_LOGIN_INFO_SQL,new Object[]{user.getLastVisit(), user.getLastIp(),user.getCredits(),user.getUserId()});
}
}
LoginLogDao.java
package com.smart.dao;
import com.smart.domain.LoginLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class LoginLogDao {
private JdbcTemplate jdbcTemplate;
//保存登陆日志SQL
private final static String INSERT_LOGIN_LOG_SQL=" INSERT INTO t_login_log(user_id,ip,login_datetime) values(?,?,?) ";
public void insertLoginLog(LoginLog loginLog){
Object [] args={loginLog.getUserId(),loginLog.getIp(),loginLog.getLoginDate()};
jdbcTemplate.update(INSERT_LOGIN_LOG_SQL,args);
}
@Autowired
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate=jdbcTemplate;
}
}
User.java
package com.smart.domain;
import java.io.Serializable;
import java.sql.Timestamp;
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 Timestamp 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;
}
public String getLastIp() {
return lastIp;
}
public void setLastIp(String lastIp) {
this.lastIp = lastIp;
}
public Timestamp getLastVisit() {
return lastVisit;
}
public void setLastVisit(Timestamp lastVisit) {
this.lastVisit = lastVisit;
}
}
LoginLog.java
package com.smart.domain;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
public class LoginLog implements Serializable {
private int loginLogId;
private int userId;
private String ip;
private Timestamp 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;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Timestamp getLoginDate() {
return loginDate;
}
public void setLoginDate(Timestamp loginDate) {
this.loginDate = loginDate;
}
}
UserService.java
package com.smart.service;
import com.smart.dao.LoginLogDao;
import com.smart.dao.UserDao;
import com.smart.domain.LoginLog;
import com.smart.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
private UserDao userDao;
private LoginLogDao loginLogDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Autowired
public void setLoginLogDao(LoginLogDao loginLogDao) {
this.loginLogDao = loginLogDao;
}
public boolean hasMatchUser(String userName,String password){
int matchCount=userDao.getMatchCount(userName,password);
return matchCount>0;
}
public User findUserByUserName(String userName){
return userDao.findUserByUserName(userName);
}
@Transactional
public void loginSuccess(User user){
user.setCredits(5+user.getCredits());//每登录一次赚5积分
LoginLog loginLog=new LoginLog();
loginLog.setUserId(user.getUserId());
loginLog.setIp(user.getLastIp());
loginLog.setLoginDate(user.getLastVisit());
userDao.updateLoginInfo(user);
loginLogDao.insertLoginLog(loginLog);
}
}
LoginController.java
package com.smart.web;
import com.smart.domain.User;
import com.smart.service.UserService;
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 javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.Date;
@Controller
public class LoginController {
@Autowired
private UserService userService;
//负责处理/index.html的请求
@RequestMapping("/index.html")
public String loginPage(){
return "login";
}
//负责处理/loginCheck.html的请求
@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 Timestamp(new Date().getTime()));
userService.loginSuccess(user);
request.getSession().setAttribute("user",user);
return new ModelAndView("main");
}
}
}
LoginCommand.java
package com.smart.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;
}
}
package com.smart.service;
import com.smart.dao.LoginLogDao;
import com.smart.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
import org.testng.annotations.Test;
import java.sql.Timestamp;
import java.util.Date;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@ContextConfiguration("classpath*:/smart-context.xml")//启动Spring容器
public class UserServiceTest extends AbstractTransactionalTestNGSpringContextTests {
private UserService userService;
private LoginLogDao loginLogDao;
@Autowired//注入Spring中的Bean
public void setUserService(UserService userService){
this.userService=userService;
}
@Test
public void hasMatchUser(){
boolean b1=userService.hasMatchUser("admin","123456");
boolean b2=userService.hasMatchUser("admin","1111");
User user=new User();
user.setUserName("admin");
user.setPassword("123456");
assertTrue(b1);
assertTrue(!b2);
}
@Test
public void findUserByUserName(){
User user=userService.findUserByUserName("admin");
assertEquals(user.getUserName(),"admin");
}
@Test
public void testAddLoginLog() {
User user = userService.findUserByUserName("admin");
user.setUserId(1);
user.setUserName("admin");
user.setLastIp("192.168.12.7");
user.setLastVisit(new Timestamp(new Date().getTime()));
userService.loginSuccess(user);
System.out.println("盐勺水fklajfakfklanjf");
}
public static void main(String[] args) {
System.out.println("盐勺水fklajfakfklanjf");
}
}
login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: yan
Date: 2018/10/31
Time: 22:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
小春论坛登录
<%--判空--%>
" method="post">
用户名:
密码:
main.jsp
<%--
Created by IntelliJ IDEA.
User: yan
Date: 2018/10/31
Time: 22:19
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
小春论坛
${user.userName},欢迎进入小春论坛,当前积分为${user.credits};
首先用户访问login.jsp,返回登录页面
用户输入用户名密码,Spring根据配置调用LoginController控制器接受请求并交给后台处理
LoginController调用UserService的hasMatchUser(),其再调用UserDao的getMatchCount()方法查询数据库中是否存在该用户/密码对
如果不存在则重定向回login.jsp并用ModelAndView封装错误参数键值对给login.jsp以提示
如果存在则LoginController调用UserService的findUserByUserName()方法,取得登录用户信息,并将用户信息封装到session中
LoginController调用 UserService的loginSuccess()方法,进行前面所述的登录成功业务处理
后台处理完毕,重定向到欢迎页面main.jsp
根据下面的配置信息得到项目访问路径:
maven中jetty配置:
Spring MVC中LoginController配置
所以正确的访问路径为:
http://localhost:8000/bbs/index.html
访问效果: