在
中实现了SSM整合,现在进行一个基本的案例。
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
`realname` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '真实姓名',
`password` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码',
`gender` tinyint(1) UNSIGNED NULL DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学生姓名',
`score` double(10, 2) NULL DEFAULT NULL COMMENT '学生成绩',
`photo` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像路径',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
package edu.hncj.ssm.pojo;
public class User {
private Integer id;
private String username;
private String realname;
private String password;
private Boolean gender;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRealname() {
return realname;
}
public void setRealname(String realname) {
this.realname = realname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Boolean getGender() {
return gender;
}
public void setGender(Boolean gender) {
this.gender = gender;
}
public User() {
}
public User(Integer id, String username, String realname, String password, Boolean gender) {
this.id = id;
this.username = username;
this.realname = realname;
this.password = password;
this.gender = gender;
}
}
在edu.hncj.ssm.mapper包下创建UserMapper接口
package edu.hncj.ssm.mapper;
import edu.hncj.ssm.pojo.User;
public interface UserMapper {
//根据用户查询用户
User findByUserName(String username);
//保存用户信息
void save(User user);
}
在resources的edu/hncj/ssm/mapper目录下创建UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="edu.hncj.ssm.mapper.UserMapper">
<!--findByUserName-->
<select id="findByUserName" parameterType="String" resultType="User">
select id,username,realname,password,gender from `user`
where username = #{username}
</select>
<!--save-->
<insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into `user` values(#{id},#{username},#{realname},#{password},#{gender})
</insert>
</mapper>
UserSerivice:
package edu.hncj.ssm.service;
import edu.hncj.ssm.pojo.User;
public interface UserService {
//注册用户
void register(User user);
//用户登录
User login(String username, String password);
}
UserSeriviceImpl:
package edu.hncj.ssm.service.impl;
import edu.hncj.ssm.mapper.UserMapper;
import edu.hncj.ssm.pojo.User;
import edu.hncj.ssm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import java.nio.charset.StandardCharsets;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userDao;
@Autowired
public UserServiceImpl(UserMapper userDao) {
this.userDao = userDao;
}
@Override//xiaochen 123 ====> xiaochen xxed
public User login(String username, String password) {
//1.根据用户名查询用户
User user = userDao.findByUserName(username);
if(ObjectUtils.isEmpty(user)) throw new RuntimeException("用户名不正确!");
//2.比较密码
String passwordSecret = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
if(!user.getPassword().equals(passwordSecret)) throw new RuntimeException("密码输入错误!");
return user;
}
@Override
public void register(User user) {
//1.根据用户名查询数据库中是否存在改用户
User userDB = userDao.findByUserName(user.getUsername());
//2.判断用户是否存在
if(!ObjectUtils.isEmpty(userDB)) throw new RuntimeException("当前用户名已被注册!");
//3.注册用户&明文的密码加密 特点: 相同字符串多次使用md5就行加密 加密结果始终是一致
String newPassword = DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8));
user.setPassword(newPassword);
userDao.save(user);
}
}
VerifyCodeUtils类
package edu.hncj.ssm.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;
/**
*/
public class VerifyCodeUtils {
/**
* 输出指定验证码图片流
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
Color.PINK, Color.YELLOW };
float[] fractions = new float[colors.length];
for(int i = 0; i < colors.length; i++){
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();
}
Arrays.sort(fractions);
g2.setColor(Color.GRAY);// 设置边框色
g2.fillRect(0, 0, w, h);
g2.setColor(Color.gray);// 设置背景色
g2.fillRect(0, 2, w, h-4);
g2.setColor(Color.blue);
int fontSize = h-4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for(int i = 0; i < verifySize; i++){
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);
}
g2.dispose();
ImageIO.write(image, "jpg", os);
}
}
package edu.hncj.ssm.controller;
import edu.hncj.ssm.pojo.User;
import edu.hncj.ssm.service.UserService;
import edu.hncj.ssm.utils.VerifyCodeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@Controller
@RequestMapping("user")
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
/**
* 安全退出
*/
@RequestMapping("logout")
public String logout(HttpSession session) {
session.invalidate(); //session失效
return "redirect:/user/login";//跳转到登录界面
}
/**
* 用户登录
*
* @return
*/
@RequestMapping("login")
public String login(String username, String password, HttpSession session) {
log.debug("本次登录用户名: {}", username);
log.debug("本地登录密码: {}", password);
try {
//1.调用业务层进行登录
User user = userService.login(username, password);
//2.保存用户信息
session.setAttribute("user", user);
} catch (Exception e) {
e.printStackTrace();
return "login";//登录失败回到登录界面
}
return "redirect:/student/lists";//登录成功之后,跳转到查询所有员工信息控制器路径
}
/**
* 用户注册
*
* @return
*/
@RequestMapping("register")
public String register(User user, String code, HttpSession session) {
log.debug("用户名: {},真是姓名: {},密码: {},性别: {},", user.getUsername(), user.getRealname(), user.getPassword(), user.getGender());
log.debug("用户输入验证码: {}", code);
try {
//1.判断用户输入验证码和session中验证码是否一致
String sessionCode = session.getAttribute("code").toString();
if (!sessionCode.equalsIgnoreCase(code)) throw new RuntimeException("验证码输入错误!");
//2.注册用户
userService.register(user);
} catch (RuntimeException e) {
e.printStackTrace();
return "register"; //注册失败回到注册
}
return "redirect:/user/login"; //注册成功跳转到登录
}
/**
* 生成验证码
*/
@RequestMapping("generateImageCode")
public void generateImageCode(HttpSession session, HttpServletResponse response) throws IOException {
//1.生成4位随机数
// String code = VerifyCodeUtils.generateVerifyCode(4);
String code = "1235";
//2.保存到session作用域
session.setAttribute("code", code);
//3.根据随机数生成图片 && 4.通过response响应图片 && 5.设置响应类型
response.setContentType("image/png");
ServletOutputStream os = response.getOutputStream();
VerifyCodeUtils.outputImage(220, 60, os, code);
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>用户登录</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"/>
</head>
<body>
<div id="wrap">
<div id="top_content">
<div id="header">
<div id="topheader">
<h1 id="title">
<a href="#">main</a>
</h1>
</div>
<div id="navigation">
</div>
</div>
<div id="content">
<p id="whereami">
</p>
<h1> 欢迎进入,请登录! </h1>
<form th:action="@{/user/login}" method="post">
<table cellpadding="0" cellspacing="0" border="0"
class="form_table">
<tr>
<td valign="middle" align="right">用户名:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="username"/>
</td>
</tr>
<tr>
<td valign="middle" align="right">密码:</td>
<td valign="middle" align="left">
<input type="password" class="inputgri" name="password"/>
</td>
</tr>
</table>
<p>
<input type="submit" class="button" value="点我登录 »"/>
<a href="register">还没有账号,立即注册</a>
</p>
</form>
</div>
</div>
<div id="footer">
<div id="footer_bg">
123@qq.com
</div>
</div>
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>用户注册</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" />
</head>
<body>
<div id="wrap">
<div id="top_content">
<div id="header">
<div id="topheader">
<h1 id="title">
<a href="#">main</a>
</h1>
</div>
<div id="navigation">
</div>
</div>
<div id="content">
<p id="whereami"></p>
<h1>注册</h1>
<form th:action="@{/user/register}" method="post">
<table cellpadding="0" cellspacing="0" border="0"
class="form_table">
<tr>
<td valign="middle" align="right">用户名:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="username" />
</td>
</tr>
<tr>
<td valign="middle" align="right">真实姓名:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="realname" />
</td>
</tr>
<tr>
<td valign="middle" align="right">密码:</td>
<td valign="middle" align="left">
<input type="password" class="inputgri" name="password" />
</td>
</tr>
<tr>
<td valign="middle" align="right">性别:</td>
<td valign="middle" align="left">
男<input type="radio" class="inputgri" name="gender" value="1" checked="checked"/>
女<input type="radio" class="inputgri" name="gender" value="0"/>
</td>
</tr>
<tr>
<td valign="middle" align="right">
验证码:
<img id="num" th:src="@{/user/generateImageCode}" />
<a href="javascript:;" onclick="changeImageCode()">换一张</a>
<script>
function changeImageCode(){
document.getElementById('num').src = '[[@{/user/generateImageCode}]]?'+(new Date()).getTime()
}
</script>
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="code" />
</td>
</tr>
</table>
<p>
<input type="submit" class="button" value="立即注册 »" />
<a href="login">已有账号,返回登录</a>
</p>
</form>
</div>
</div>
<div id="footer">
<div id="footer_bg">
123@qq.com
</div>
</div>
</div>
</body>
</html>
在src/main/webapp/css/style.css
body {
margin: 0;
font-size: 62.5%;
font-family: Verdana, Arial, Helvetica, sans-serif;
padding: 15px 0;
background: #eeeeee;
}
#wrap {
width: 820px;
margin: 0 auto;
}
#top_content {
padding: 0 10px;
}
#topheader {
padding: 25px 15px 15px 15px;
margin: 0 auto 0 auto;
color: #85C329;
}
#rightheader {
float: right;
width: 375px;
height: 40px;
text-align: right;
}
#rightheader p {
padding: 35px 15px 0 0;
margin: 0;
text-align: right;
}
#rightheader p span {
font-weight: bold;
}
#rightheader a:link, #rightheader a:visited {
text-decoration: underline;
}
#title {
padding: 0;
margin: 0;
font-size: 2.5em;
}
#title span {
font-size: 0.5em;
font-style: italic;
}
#title a:link, #title a:visited {
text-decoration: none;
}
#title a:hover {
color: #E1F3C7;
}
#navigation {
background: #85c329;
height: 25px;
clear: both
}
#navigation ul {
padding: 0;
margin: 0;
list-style: none;
font-size: 1.1em;
height: 25px;
}
#navigation ul li {
display: inline;
}
#navigation ul li a {
color: #FFFFFF;
display: block;
text-decoration: none;
float: left;
line-height: 25px;
padding: 0 16px;
border-right: 1px solid #ffffff;
}
#navigation ul li a:hover {
background: #5494F3;
}
#content {
padding: 0 15px;
margin: 0 auto 0 auto;
color: #666666;
}
#content p#whereami {
padding: 20px 0 15px 0;
margin: 0;
}
#whereami a:link, #whereami a:visited {
color: #73A822;
text-decoration: underline;
}
#content h1, #content h2,
#content h3, #content h4 , #content h5 {
color: #74A8F5;
}
#content h1 {
font-family: "Trebuchet MS", Arial, Helvetica;
padding: 0;
margin: 0 0 15px 0;
font-size: 2em;
}
#content h2 {
font-family: "Trebuchet MS", Arial, Helvetica;
padding: 0;
margin: 0 0 15px 0;
font-size: 1.5em;
}
#top_body, #content_body {
padding: 0 25px;
}
#footer {
color: #FFFFFF;
padding: 0 10px 13px 10px;
}
#footer p {
padding: 0;
margin: 0;
}
#footer p a:link, #footer p a:visited {
color: #FFFFFF;
font-style: italic;
text-decoration: none;
}
#footer #footer_bg {
color: #85C329 ;
padding: 15px 15px 25px 15px;
border-top: 1px solid #7BB425;
}
#footer #design {
display: block;
width: 150px;
height: 30px;
float: right;
line-height: 20px;
padding: 0 5px;
text-align: right;
color: #E1F3C7;
}
#footer #design a {
color: #FFFFFF;
text-decoration: underline;
}
.table {
margin-bottom: 15px;
width: 100%;
border-collapse: collapse;
}
.table_header td {
padding: 5px 10px;
color: rgb(70,122,167);
border-top: 1px solid #CBD6DE;
border-bottom: 1px solid #ADBECB;
font-size: 1.1em;
font-weight: bold;
}
.table_header td a:link, .table_header td a:visited {
text-decoration: underline;
color: rgb(70,122,167);
}
.table_header td a:hover {
text-decoration: underline;
color: #73A822;
}
.table_header td {
border: 1px solid #CBD6DE;
}
.row1 td, .row2 td, .row_hover td, .paging_row td {
padding: 5px 10px;
color: #666666;
border: 1px solid #CBD6DE;
}
.row1 td {
background: #ffffff;
}
.row2 td {
background: #eeeeee;
}
.row_hover td {
background: #FBFACE;
color: #000000;
}
.hidden {
display: none;
}
.little {
font-size: 10px;
}
.clear {
clear: both;
}
.img_left {
float: left;
padding: 1px;
border: 1px solid #cccccc;
margin: 0 10px 10px 0;
width: 110px;
height:150px;
}
/* #content ul basic style for unordered lists
------------------------------------------------*/
#content ul {
font-size: 1.1em;
line-height: 1.8em;
margin: 0 0 15px 0;
padding: 0;
list-style-type: none;
}
/* #content p paragraphs
-----------------------------*/
#content p {
font-size: 1.2em;
margin: 0;
padding: 0 0 15px 0;
}
/* #content p a links in paragraphs
------------------------------------*/
#content p a:link, #content p a:visited,
.table a:link, .table a:visited,
.link a {
color: #73A822;
text-decoration: none;
}
#content p a:hover, .table a:hover, .link a:hover {
text-decoration: underline;
}
/* #content ul.green (73A822)
--------------------------------*/
#content ul.green li {
padding: 0 0 0 20px;
margin: 0;
font-size: 1.1em;
}
#content ul.green li a:link, #content ul.green li a:visited {
color: #73A822;
text-decoration: none;
}
#content ul.green li a:hover {
color: #73A822;
text-decoration: underline;
}
/* #content ul.black (73A822)
--------------------------------*/
#content ul.black li {
padding: 0 0 0 20px;
margin: 0;
font-size: 1.1em;
}
#content ul.black li a:link, #content ul.black li a:visited {
color: #666666;
text-decoration: none;
}
#content ul.black li a:hover {
color: #999999;
text-decoration: underline;
}
/* #content ol
--------------------------------*/
#content ol {
padding: 0 0 0 25px;
margin: 0 0 15px 0;
line-height: 1.8em;
}
#content ol li {
font-size: 1.1em;
}
#content ol li a:link, #content ol li a:visited {
color: #73A822;
text-decoration: none;
}
#content ol li a:hover {
color: #73A822;
text-decoration: underline;
}
/* #content p.paging
---------------------------------*/
#content p.paging {
padding: 5px;
border: 1px solid #CBD6DE;
text-align: center;
margin-bottom: 15px;
background: #eeeeee;
}
/* .small_input smaller text in inputs/combos
-----------------------------------------------*/
.small_input {
font-size: 10px;
}
/* .form_table style for table used in forms
---------------------------------------------*/
.form_table {
margin-bottom: 15px;
font-size: 1.1em;
}
.form_table p {
margin: 0;
padding: 0;
}
.form_table td {
padding: 5px 10px;
}
/* .checkbox_nomargins clear all margins from a checkbox
---------------------------------------------------------*/
.checkbox_nomargins {
margin: 0;
padding: 0;
}
/* .button some buttons style - inspired from wordpress
------------------------------*/
input.button {
margin: 0;
padding: 2px;
border: 3px double #999999;
border-left-color: #ccc;
border-top-color: #ccc;
font-size: 11px;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
/* form style for forms
-------------------------*/
form {
padding: 0;
margin: 0;
}
/* input.inputgri - some style for inputs
--------------------------------------------*/
input.inputgri, select.inputgri, textarea.inputgri {
background: #eeeeee;
font-size: 14px;
border: 1px solid #cccccc;
padding: 3px;
}
input.inputgri:focus, select.inputgri:focus , textarea.inputgri:focus {
background: #ffffff;
border: 1px solid #686868;
}
/* .notice - messages to user
--------------------------------*/
.notice {
background: #CAEA99;
border: 1px solid #70A522;
padding: 15px 15px 15px 15px;
margin-bottom: 15px;
font-size: 1.2em;
color: #333333;
}
.notice_error {
background: #FEDCDA;
border: 1px solid #CE090E;
padding: 15px 15px 15px 15px;
margin-bottom: 15px;
font-size: 1.2em;
color: #333333;
}
#notice a {
color: #333333;
text-decoration: underline;
}
/* Other links
----------------*/
.other_links {
background: #eeeeee;
border-top: 1px solid #cccccc;
padding: 5px;
margin: 0 0 15px 0;
}
#content .other_links h2 {
color: #999999;
padding: 0 0 0 3px;
margin: 0;
}
#content .other_links ul {
padding: 0;
margin: 0;
}
#content .other_links ul li {
padding: 0 0 0 20px;
}
#content .other_links a, #content .other_links a:visited {
color: #999999;
text-decoration: underline;
}
#content .other_links a:hover {
color: #666666;
}
/* code */
code {
font-size: 1.2em;
color: #73A822;
}
在edu.hncj.ssm.config下创建LoginHandlerInterceptor:
package edu.hncj.ssm.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 登录成功应该有session(在登陆的Controller中设置session)
Object admin = request.getSession().getAttribute("user");
System.out.println(admin);
if (admin == null){
request.setAttribute("msg", "没有权限,请先登录!");
request.getRequestDispatcher("/user/login").forward(request, response);
return false;
}else {
return true;
}
}
}
配置拦截器:
在springmvc中添加拦截器配置
<mvc:interceptors>
<mvc:interceptor>
<!-- 所有请求都拦截-->
<mvc:mapping path="/**"/>
<!-- 放行登录界面和登陆请求-->
<mvc:exclude-mapping path="/user/login"/>
<mvc:exclude-mapping path="/user/register"/>
<mvc:exclude-mapping path="/user/generateImageCode"/>
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/upload/**"/>
<mvc:exclude-mapping path="/js/**"/>
<!-- 拦截器类的位置-->
<bean class="edu.hncj.ssm.config.LoginHandlerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
在 edu.hncj.ssm.pojo 下创建 Student类
package edu.hncj.ssm.pojo;
public class Student {
private Integer id;
private String name;
private Double score;
private String photo;//头像路径
public Student() {
}
public Student(Integer id, String name, Double score, String photo) {
this.id = id;
this.name = name;
this.score = score;
this.photo = photo;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
}
在edu.hncj.ssm.mapper包下创建StudentMapper接口:
package edu.hncj.ssm.mapper;
import edu.hncj.ssm.pojo.Student;
import java.util.List;
public interface StudentMapper {
//学生列表
List<Student> lists();
//保存学生信息
void save(Student student);
//根据id查询一个
Student findById(Integer id);
//更新学生信息
void update(Student student);
//删除学生信息
void delete(Integer id);
}
在resources的edu/hncj/ssm/mapper目录下创建StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="edu.hncj.ssm.mapper.StudentMapper">
<!--lists-->
<select id="lists" resultType="Student">
select id,name,score,photo from `student`
</select>
<!--save-->
<insert id="save" parameterType="Student" useGeneratedKeys="true" keyProperty="id">
insert into `student` values (#{id},#{name},#{score},#{photo})
</insert>
<!--findById-->
<select id="findById" parameterType="Integer" resultType="Student">
select id,name,score,photo from `student`
where id = #{id}
</select>
<!--update-->
<update id="update" parameterType="Student" >
update `student` set name=#{name},score=#{score},photo=#{photo}
where id = #{id}
</update>
<!--delete-->
<delete id="delete" parameterType="Integer">
delete from `student` where id = #{id}
</delete>
</mapper>
在edu.hncj.ssm.service下创建StudentService。
package edu.hncj.ssm.service;
import edu.hncj.ssm.pojo.Student;
import java.util.List;
public interface StudentService {
//学生列表方法
List<Student> lists();
//保存学生信息
void save(Student student);
//根据id查询一个
Student findById(Integer id);
//更新学生信息
void update(Student student);
//删除学生信息
void delete(Integer id);
}
在edu.hncj.ssm.service.impl下创建StudentServiceImpl
package edu.hncj.ssm.service.impl;
import edu.hncj.ssm.mapper.StudentMapper;
import edu.hncj.ssm.pojo.Student;
import edu.hncj.ssm.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class StudentServiceImpl implements StudentService {
private StudentMapper studentMapper;
@Autowired
public StudentServiceImpl(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
public void delete(Integer id) {
studentMapper.delete(id);
}
@Override
public void update(Student student) {
studentMapper.update(student);
}
@Override
public Student findById(Integer id) {
return studentMapper.findById(id);
}
@Override
public void save(Student employee) {
studentMapper.save(employee);
}
@Override
public List<Student> lists() {
return studentMapper.lists();
}
}
在edu.hncj.ssm.controller下创建StudentController
package edu.hncj.ssm.controller;
import edu.hncj.ssm.pojo.Student;
import edu.hncj.ssm.service.StudentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("student")
public class StudentController {
private static final Logger log = LoggerFactory.getLogger(StudentController.class);
private StudentService service;
@Value("G:\\ideaproject\\chapter15\\src\\main\\webapp\\upload")
private String realpath;
@Autowired
public StudentController(StudentService employeeService) {
this.service = employeeService;
}
/**
* 删除学生信息
* @param id
* @return
*/
@RequestMapping("delete")
public String delete(Integer id){
log.debug("删除的学生id: {}",id);
//1.删除数据
String photo = service.findById(id).getPhoto();
service.delete(id);
//2.删除头像
File file = new File(realpath, photo);
if (file.exists()) file.delete();
return "redirect:/student/lists";//跳转到学生列表
}
/**
* 更新学生信息
*
* @param student
* @param img
* @return
*/
@RequestMapping("update")
public String update(Student student, MultipartFile img) throws IOException {
log.debug("更新之后学生信息: id:{},姓名:{},成绩:{}", student.getId(), student.getName(), student.getScore());
//1.判断是否更新头像
boolean notEmpty = !img.isEmpty();
log.debug("是否更新头像: {}", notEmpty);
if (notEmpty) {
//1.删除老的头像 根据id查询原始头像
String oldPhoto = service.findById(student.getId()).getPhoto();
File file = new File(realpath, oldPhoto);
if (file.exists()) file.delete();//删除文件
//2.处理新的头像上传
String originalFilename = img.getOriginalFilename();
String newFileName = uploadPhoto(img, originalFilename);
//3.修改学生新的头像名称
student.setPhoto(newFileName);
}
//2.没有更新头像直接更新基本信息
service.update(student);
return "redirect:/student/lists";//更新成功,跳转到学生列表
}
//上传头像方法
private String uploadPhoto(MultipartFile img, String originalFilename) throws IOException {
String fileNamePrefix = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
String fileNameSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String newFileName = fileNamePrefix + fileNameSuffix;
img.transferTo(new File(realpath, newFileName));
return newFileName;
}
/**
* 根据id查询学生详细信息
*
* @param id
* @param model
* @return
*/
@RequestMapping("detail")
public String detail(Integer id, Model model) {
log.debug("当前查询学生id: {}", id);
//1.根据id查询一个
Student student = service.findById(id);
model.addAttribute("student", student);
return "updateStu";//跳转到更新页面
}
/**
* 保存学生信息
* 文件上传: 1.表单提交方式必须是post 2.表单enctype属性必须为 multipart/form-data
*
* @return
*/
@RequestMapping("save")
public String save(Student employee, MultipartFile img) throws IOException {
log.debug("姓名:{}, 成绩:{} ", employee.getName(), employee.getScore());
String originalFilename = img.getOriginalFilename();
log.debug("头像名称: {}", originalFilename);
log.debug("头像大小: {}", img.getSize());
log.debug("上传的路径: {}", realpath);
//1.处理头像的上传&修改文件名称
String newFileName = uploadPhoto(img, originalFilename);
//2.保存学生信息
employee.setPhoto(newFileName);//保存头像名字
service.save(employee);
return "redirect:/student/lists";//保存成功跳转到列表页面
}
/**
* 学生列表
*
* @return
*/
@RequestMapping("lists")
public String lists(Model model) {
log.debug("查询所有学生信息");
List<Student> studentlist = service.lists();
model.addAttribute("studentlist", studentlist);
return "studentlist";
}
/**
* 添加学生列表
* @return
*/
@RequestMapping("addStu")
public String addStu(Model model) {
log.debug("新增学生信息");
return "addStu";
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>studentlist</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" />
</head>
<body>
<div id="wrap">
<div id="top_content">
<div id="header">
<div id="rightheader">
<p>
<a th:if="${session.user!=null}" th:href="@{/user/logout}">安全退出</a>
<a th:if="${session.user==null}" th:href="@{/user/login}">点我登录</a>
</p>
</div>
<div id="topheader">
<h1 id="title">
<a href="#">主页</a>
</h1>
</div>
<div id="navigation">
</div>
</div>
<div id="content">
<p id="whereami">
</p>
<h1>欢迎
<span th:if="${session.user!=null}" th:text="${session.user.username}"></span>
<span th:if="${session.user==null}" >游客</span>!
</h1>
<table class="table">
<tr class="table_header">
<td>编号</td><td>姓名</td><td>头像</td><td>成绩</td><td>操作</td>
</tr>
<tr th:each="student,state:${studentlist}" th:class="${state.odd?'row1':'row2'}">
<td><span th:text="${student.id}"></span></td>
<td><span th:text="${student.name}"></span></td>
<td><img th:src="@{/upload/}+${student.photo}" width="60"></td>
<td><span th:text="${student.score}"></span></td>
<td>
<a href="javascript:;" th:onclick="'deleteStudent('+${student.id}+')'">删除</a>
<a th:href="@{/student/detail(id=${student.id})}">更新</a>
</td>
</tr>
<script>
function deleteStudent(id){
console.log(id);
if(window.confirm('确定要删除这条记录吗?')){
location.href='[[@{/student/delete?id=}]]'+id;
}
}
</script>
</table>
<p>
<input type="button" class="button" value="添加" onclick="addStu()"/>
<script>
function addStu(){
location.href = '[[@{/student/addStu}]]';
}
</script>
</p>
</div>
</div>
<div id="footer">
<div id="footer_bg">
123@qq.com
</div>
</div>
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymealf.org">
<head>
<title>添加学生信息</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css"
href="/css/style.css" />
</head>
<body>
<div id="wrap">
<div id="top_content">
<div id="header">
<div id="rightheader">
</div>
<div id="topheader">
<h1 id="title">
<a href="#">main</a>
</h1>
</div>
<div id="navigation">
</div>
</div>
<div id="content">
<p id="whereami"></p>
<h1>添加学生信息:</h1>
<form th:action="@{/student/save}" method="post" enctype="multipart/form-data">
<table cellpadding="0" cellspacing="0" border="0"
class="form_table">
<tr>
<td valign="middle" align="right">姓名:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="name" />
</td>
</tr>
<tr>
<td valign="middle" align="right">头像:</td>
<td valign="middle" align="left">
<input type="file" width="" name="img" />
</td>
</tr>
<tr>
<td valign="middle" align="right">成绩:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="score" />
</td>
</tr>
</table>
<p>
<input type="submit" class="button" value="确认添加" />
<input type="submit" class="button" value="返回列表" />
</p>
</form>
</div>
</div>
<div id="footer">
<div id="footer_bg">
123@qq.com
</div>
</div>
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>更新学生信息</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css"
th:href="@{/css/style.css}" />
</head>
<body>
<div id="wrap">
<div id="top_content">
<div id="header">
<div id="rightheader">
</div>
<div id="topheader">
<h1 id="title"><a href="#">main</a></h1>
</div>
<div id="navigation">
</div>
</div>
<div id="content">
<p id="whereami"></p>
<h1>更新学生信息:</h1>
<form th:action="@{/student/update}" method="post" enctype="multipart/form-data">
<table cellpadding="0" cellspacing="0" border="0"
class="form_table">
<tr>
<td valign="middle" align="right">编号:</td>
<td valign="middle" align="left">
<span th:text="${student.id}"></span>
<input type="hidden" name="id" th:value="${student.id}">
</td>
</tr>
<tr>
<td valign="middle" align="right">姓名:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="name" th:value="${student.name}"/>
</td>
</tr>
<tr>
<td valign="middle" align="right">当前头像:</td>
<td valign="middle" align="left">
<img th:src="@{/upload/}+${student.photo}" width="60">
<input type="hidden" th:value="${student.photo}" name="photo">
</td>
</tr>
<tr>
<td valign="middle" align="right">选择新头像:</td>
<td valign="middle" align="left">
<input type="file" name="img" />
</td>
</tr>
<tr>
<td valign="middle" align="right">成绩:</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="score" th:value="${student.score}"/>
</td>
</tr>
</table>
<p>
<input type="submit" class="button" value="更新" />
<input type="button" class="button" value="返回列表" onclick="lists()" />
<script>
function lists(){
location.href = '[[@{/student/lists}]]';
}
</script>
</p>
</form>
</div>
</div>
<div id="footer">
<div id="footer_bg">
123@qq.com
</div>
</div>
</div>
</body>
</html>
目前为止,项目工程结构为:
运行项目,访问
http://localhost:8080/user/login
进入登录页面,内容如下:
点击还没有账号,立即注册,如下:
注册完成后,跳到到登录页面,登录成功后,跳到到学生列表页
点击添加,可以添加学生信息
添加完学生信息后,返回学生列表页
点击更新后,跳转到更新页面
点击删除后,弹出确认框
删除后,跳转回学生列表页
点击安全退出后,由于拦截器的作用,跳转到登录页面