您的位置:首页 > 编程语言 > Java开发

【SSM】Spring+SpringMVC+MyBatis整合之学生管理系统

2019-06-16 19:15 495 查看

刚刚学习完SSM整合 就想着自己写一个学生管理系统…
一.搭建环境
1.创建数据库和创建表
做学生管理系统 肯定是需要2张表的
第一就是User表 用来管理用户名和密码
第二就是Student表 用来存储学生的信息


2.SSM环境搭建
创建一个Maven的web项目之后
首先导入我们之前自己整合的一些文件(这里我博客都有写,这里就不一一列举了)
pom.xml坐标文件,
applicationContext.xml配置文件,
jdbc.properties文件,
log4j.properties文件,
spring-mvc.xml配置文件,
web.xml配置文件(我经常忘记配这个文件 所以经常404~~)


创建我们的三层架构

引入我们前端的页面

创建测试类代码(主要做一些测试)

二,项目流程分析
点击Tomcat运行>>index.jsp

首页可以>>查询所有学生信息
我这边写了一个过滤器 如果没有登陆的话会让我们去登陆

当然如果你是第一次访问的话还没有账号可以去注册>>点击还没账号?去注册

我这边注册页面就写的比较简单 只有用户名和密码
当然如果你向后台提交空的用户名和密码还是会有相应的错误提示
记得在过滤器中一定要放行我们的登陆方法和注册方法
不然就会一直让你登陆 不会出现错误页面

点击>>重新注册返回注册界面>>注册成功>>跳转到登陆界面

输入正确的账号密码和验证码>>跳转到首页
这边红框中的两个功能我在后台是有逻辑判断的.但自动登陆的过滤器我这边就没有写
后期会补上~

这时候已经是登陆状态了>>查询所有学生信息

添加学生功能

这边重置和返回功能我这边还没写 后期完善会补上~
修改学生功能

修改学生这边会回显数据 所以在修改学生之前 我们实际上先要获取要修改的学生id
通过id去后台找到这个学生 再将找到的学生对象存到域对象中 获取回显数据
然后修改信息再提交到后台
删除学生功能

为了防止用户误操作 删除信息之前给出相应的提示
当用户点击确定 再去操作删除功能
点击取消 则返回界面
同理删除选中按钮功能也会给出相应的提示

接下来就是这个项目我个人认为比较复杂的功能
多条件查询和分页功能
思考一下,由于用户需要查询的条件不同的话,那么向我们后台传递的条件也可能是不同的
所以我们访问数据库时需要查询的sql语句也是不同的.
这个时候就需要用到Mybatis的动态sql
常见的Mybatis的动态sql写法是XML文件配置
我这个项目在Dao层都是用注解来开发的
那么注解是如何实现动态sql的呢?
我个人也在网上找了一些资料
然后向同学也取了取经,给出一种比较简单的用法.
在Dao层创建一个Provider的包 创建一个StudentDaoProvider 类

package com.itheima.dao.Provider;

import com.itheima.domain.Student;

public class StudentDaoProvider {

public String findStudentByPage(Student student) {
String name = student.getName();
String sex = student.getSex();
String address = student.getAddress();

String sql = "select * from student where 1 = 1";
if(name!=null&&!"null".equalsIgnoreCase(name)&&!"".equals(name)){
sql += " and name like '%"+name+"%' ";
}
if(sex!=null&&!"null".equalsIgnoreCase(sex)&&!"".equals(sex)){
sql += " and sex = '"+sex+"' ";
}
if(address!=null&&!"null".equalsIgnoreCase(address)&&!"".equals(address)){
sql += " and address = '"+address+"' ";
}
return sql;
}
}

这个类会返回一个sql语句 它会根据你从后台传来是Student对象取里面的属性值判断有没有内容
如果有内容就会给你判断 然后拼接你的sql
Dao层用到的是@SelectProvider注解
里面的参数是类型 加载类的字节码文件
方法 你要调用的是类中的哪个方法
也就相当于将类中返回的sql返回到这里执行查询条件了!

@SelectProvider(type = StudentDaoProvider.class,method = "findStudentByPage")
List<Student> findStudentByPage(Student student);

我们来看一下日志效果
比如我们就查询两个条件
查询

红框中就是动态生成的sql 可以看到是两个参数并且会自动给我们带上分页的语句
返回的对象是一个

接下来说一下分页功能
在JavaWeb阶段我们在做分页功能的时候其实是非常的繁琐的 需要很多参数
比如当前页 开始页码 每页要展示的条数 总页数 总条数
有时候还需要计算一些值
在Mybatis框架中就很好的为我们解决了这个问题
所以这可能就是Mybatis框架带来的魅力吧!
直接先上代码
配置分页插件

<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--给实体类起别名-->
<property name="typeAliasesPackage" value="com.itheima.domain"/>
<!--配置分页插件-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>dialect=mysql</value>
</property>
</bean>
</array>
</property>
</bean>

在查询语句前调用方法(传入当前页+每页显示的条数)两个参数

//设置分页相关参数   当前页+每页显示的条数
PageHelper.startPage(pageNums,pageSizes);
List<Student> studentList = studentService.findStudentByPage(student);
//将查询条件存到request共享域中
request.setAttribute("student",student);
//获得与分页相关参数
PageInfo<Student> pageInfo = new PageInfo<Student>(studentList);

将返回的List集合封装到PageInfo这个类中
这个类很强大包括刚才提到的要计算的属性 这个类都统统给你计算好了
你只需要把这个list集合set进去 然后返回这个类给前端就可以了
可以看一下效果
我为什么要把Student也放到共享域中呢? 其实是为了在查询条件出来结果的时候
能把查询条件也回显给用户
前台又是如何展示这个数据的呢?

<c:forEach items="${pageInfo.list}" var="student" varStatus="s">
<tr>
<td><input type="checkbox" name="uid" value="${student.id}"></td>
<td>${student.id}</td>
<td>${student.name}</td>
<td>${student.age}</td>
<td>${student.sex}</td>
<td>${student.date}</td>
<td>${student.email}</td>
<td>${student.address}</td>
<td>
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findStudentById?id=${student.id}">修改</a>&nbsp;
<a class="btn btn-default btn-sm" href="javascript:deleteStudentById(${student.id});">删除</a></td>
</td>
</tr>
</c:forEach>

分页条

<div style="text-align: center;">
<nav aria-label="Page navigation">
<ul class="pagination">
<%--上一页--%>
<c:if test="${pageInfo.pageNum == 1}">
<li class="disabled">
</c:if>
<c:if test="${pageInfo.pageNum != 1}">
<li>
</c:if>
<a href="${pageContext.request.contextPath}/findStudentByPage?pageNum=${pageInfo.pageNum - 1}&pageSize=5&name=${student.name}&sex=${student.sex}&address=${student.address}"aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>

<%--页码 判断页码状态--%>
<c:forEach begin="1" end="${pageInfo.pages}" var="i" >
<c:if test="${pageInfo.pageNum == i}">
<li class="active"><a href="${pageContext.request.contextPath}/findStudentByPage?pageNum=${i}&pageSize=5&name=${student.name}&sex=${student.sex}&address=${student.address}">${i}</a></li>
</c:if>
<c:if test="${pageInfo.pageNum != i}">
<li><a href="${pageContext.request.contextPath}/findStudentByPage?pageNum=${i}&pageSize=5&name=${student.name}&sex=${student.sex}&address=${student.address}">${i}</a></li>
</c:if>
</c:forEach>

<%--下一页 判断页码状态--%>
<c:if test="${pageInfo.pageNum >= pageInfo.pages}">
<li class="disabled">
</c:if>

<c:if test="${pageInfo.pageNum < pageInfo.pages}">
<li>
</c:if>
<a href="${pageContext.request.contextPath}/findStudentByPage?pages=${pageInfo.pages}&pageNum=${pageInfo.pageNum  + 1}&pageSize=5&name=${student.name}&sex=${student.sex}&address=${student.address}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
<br>
<br>
<%--显示记录和总页码--%>
<span style="font-size: 17px;color: red;">
共${pageInfo.total}条记录,共${pageInfo.pages}页
</span>
</ul>
</nav>
</div>

分析

判断我们当前页码是否等于当前页码 如果等于就给当前页码一个

class="active"
属性
当前页是深蓝色按钮~
判断当前页码是否小于等于1 如果小于等于1 就将上一页按钮禁用

判断当前页码是否大于等于总页数 如果大于等于总页数 就将下一页按钮禁用

尽管我们在前台对上一页和下一页进行了禁用
但当我们点击时它还会访问我们的方法
所以就会产生下一页没有数据的情况
所以我们需要在后台代码也进行判断
但是我们在分页之前又拿不到总页数的值 所以针对这个问题我就思考了一下
我们从前端可以传一个总页数的值在地址栏

可以看到我们总页数是2
下一页页码成了3
我们要的效果应该是
当我们当前页码大于总页数 就把总页数的值赋给当前页面
也就是说 if3>2 就2=2
因为我们下一页是需要将当前页面+1的
为了在index.jsp不出现查询语句的错误
写了一段我自己也非常嫌弃的判断

int pagess;
if (pageNum==null||"".equals(pageNum)){
pageNum="1";
}
if (pages==null||"".equals(pages)){
int pageNums = Integer.parseInt(pageNum);
pagess = pageNums+1;
}else{
pagess = Integer.parseInt(pages);
}
if (pageSize==null||"".equals(pageSize)){
pageSize="5";
}
int pageNums = Integer.parseInt(pageNum);
if (pageNums<=0){
pageNums=1;
}
int pageSizes = Integer.parseInt(pageSize);
if (pageNums>pagess){
pageNums = pagess;
}

我这个分页条就没有测试很多页会自动伸缩的功能 所以后期可能还会改进~

controller>>StudentController

package com.itheima.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.domain.Student;
import com.itheima.service.StudentService;
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.util.List;

@Controller
public class StudentController {

@Autowired
private StudentService studentService;

/**
* 查找学生 条件查询
* */
@RequestMapping("/findStudentByPage")
public ModelAndView findStudentByPage(HttpServletRequest request,ModelAndView modelAndView,String pageNum,String pageSize,String pages,Student student/*String name,String sex ,String address*/){
int pagess;
if (pageNum==null||"".equals(pageNum)){
pageNum="1";
}
if (pages==null||"".equals(pages)){
int pageNums = Integer.parseInt(pageNum);
pagess = pageNums+1;
}else{
pagess = Integer.parseInt(pages);
}
if (pageSize==null||"".equals(pageSize)){
pageSize="5";
}
int pageNums = Integer.parseInt(pageNum);
if (pageNums<=0){
pageNums=1;
}
int pageSizes = Integer.parseInt(pageSize);
if (pageNums>pagess){
pageNums = pagess;
}//设置分页相关参数   当前页+每页显示的条数
PageHelper.startPage(pageNums,pageSizes);
List<Student> studentList = studentService.findStudentByPage(student);
//将查询条件存到request共享域中
request.setAttribute("student",student);
//获得与分页相关参数
PageInfo<Student> pageInfo = new PageInfo<Student>(studentList);modelAndView.addObject("pageInfo",pageInfo);
modelAndView.setViewName("/list.jsp");
return modelAndView;
}

/**
* 添加学生
* */
@RequestMapping("/addStudent")
public String addStudent(Student student){
studentService.addStudent(student);
return "redirect:/findStudentByPage";
}

/**
*查找学生
* */
@RequestMapping("/findStudentById")
public String findStudentById(int id,HttpServletRequest request)  {
Student student = studentService.findStudentById(id);
request.setAttribute("student",student);
return "forward:/update.jsp";
}

/**
* 修改学生
* */
@RequestMapping("/updateStudent")
public String updateStudent(Student student){
studentService.updateStudent(student);
return "redirect:/findStudentByPage";
}

/**
* 删除学生
* */
@RequestMapping("/deleteStudentById")
public String deleteStudentById(int id){
studentService.deleteStudentById(id);
return "redirect:/findStudentByPage";
}

/**
* 删除选中学生
* */
@RequestMapping("/deleteSelectedStudent")
public String deleteSelectedStudent(int[] uid){
studentService.deleteSelectedStudent(uid);
return "redirect:/findStudentByPage";

}
}

controller>>UserController

package com.itheima.controller;
import com.itheima.domain.User;
import com.itheima.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.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 登陆
* */
@RequestMapping("/login")
public ModelAndView login(User user,String checkCode,HttpServletRequest request,HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
HttpSession session = request.getSession();
String checkCode_session = (String) session.getAttribute("checkCode_session");
session.removeAttribute("checkCode_session");
//判断验证码
if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)) {
User user1 = userService.findUsernameAndPassword(user);
if (user1 == null) {
modelAndView.addObject("login_error", "用户名密码错误");
modelAndView.setViewName("/login.jsp");
return modelAndView;
} else {
//登录成功 获取用户是否勾选了保存用户名
String check_user = request.getParameter("check_user");
//获取用户是否勾选了自动登陆
String check_auto = request.getParameter("check_auto");
if ("true".equalsIgnoreCase(check_user)) {
//说明用户勾选了记住用户名
//将用户名保存到Cookie中
Cookie cookie_uu = new Cookie("uu_name", user1.getUsername());
cookie_uu.setMaxAge(60 * 60 * 24 * 7);
cookie_uu.setPath(request.getContextPath());
response.addCookie(cookie_uu);
}
if ("true".equalsIgnoreCase(check_auto)){
//说明用户勾选了自动登陆
//将用户名和密码保存到Cookie
Cookie cookie_auto = new Cookie("auto_login", user1.getUsername() + "#" + user1.getPassword());
cookie_auto.setMaxAge(60*60*24*7);
cookie_auto.setPath(request.getContextPath());
response.addCookie(cookie_auto);
}
//将用户信息存入session
session.setAttribute("user1",user1);
modelAndView.setViewName("/index.jsp");
return modelAndView;
}
}else {
session.setAttribute("cc_error","验证码错误");
modelAndView.setViewName("redirect:/login.jsp");
return modelAndView;
}
}
/**
* 注册
* */
@RequestMapping("/register")
public ModelAndView register(ModelAndView modelAndView,String username, String password){
if (username==null||username.equals("")&&password==null||password.equals("")){
//如果用户名为空 返回错误消息
modelAndView.addObject("error","用户名或密码为空");
modelAndView.setViewName("forward:/error.jsp");
return modelAndView;
}
us
4000
erService.registerUser(username,password);
modelAndView.setViewName("forward:/login.jsp");
return modelAndView;
}
/**
* 验证码
* */
@RequestMapping("/checkCode")
public void CheckCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
//服务器通知浏览器不要缓存
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//在内存中创建一个长100,宽40的图片,默认黑色背景
//参数一:长
//参数二:宽
//参数三:颜色
int width = 100;
int height = 40;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics g = image.getGraphics();
//设置画笔颜色为灰色
g.setColor(Color.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode_session = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("checkCode_session",checkCode_session);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
g.setFont(new Font("黑体", Font.BOLD,26));
//向图片上写入验证码
g.drawString(checkCode_session,25,30);
//将内存中的图片输出到浏览器
//参数一:图片对象
//参数二:图片的格式,如PNG,JPG,GIF
//参数三:图片输出到哪里去
ImageIO.write(image,"PNG",response.getOutputStream());
}
/**
* 产生4位随机字符串
*/
private String getCheckCode() {
String base = "0123456789ABCDEFGabcdefg";
int size = base.length();
Random r = new Random();
StringBuffer sb = new StringBuffer();
for(int i=1;i<=4;i++){
//产生0到size-1的随机值
int index = r.nextInt(size);
//在base字符串中获取下标为index的字符
char c = base.charAt(index);
//将c放入到StringBuffer中去
sb.append(c);
}
return sb.toString();
}
}

dao>>StudentDao

package com.itheima.dao;

import com.itheima.dao.Provider.StudentDaoProvider;
import com.itheima.domain.Student;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface StudentDao {

@Select("select * from student")
List<Student> findAllStudent();

@Insert("insert into student Values(null,#{name},#{age},#{sex},#{date},#{email},#{address})")
Integer addStudent(Student student);

@Select("select * from student where id = #{id}")
Student findStudentById(int id);

@Update("update student set name=#{name},age=#{age},sex=#{sex},date=#{date},email=#{email},address=#{address}where id=#{id}")
void updateStudent(Student student);

@Delete("delete from student where id = #{id}")
void deleteStudentById(int id);

@SelectProvider(type = StudentDaoProvider.class,method = "findStudentByPage")
List<Student> findStudentByPage(Student student);}

dao>>UserDao

package com.itheima.dao;

import com.itheima.domain.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDao {

@Insert("insert into user values(null,#{username},#{password})")
public  void registerUser(@Param("username")String username, @Param("password")String password);

@Select("select * from user where username = #{username} and password = #{password}")
User findUsernameAndPassword(User user);
}

domain实体类(忽略)

interceptor>>过滤器

package com.itheima.interceptor;

import com.itheima.domain.User;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class PrivilegeInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user1");
if (user==null){
//没有登陆
response.sendRedirect(request.getContextPath()+"/login.jsp");
return false;

}
return true;
}
}

service>>impl>>StudentServiceImpl

package com.itheima.service.impl;

import com.itheima.dao.StudentDao;
import com.itheima.domain.Student;
import com.itheima.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 {

@Autowired
private StudentDao studentDao;

@Override
public List<Student> findAllStudent() {
return studentDao.findAllStudent();
}

@Override
public void addStudent(Student student) {
studentDao.addStudent(student);

}

@Override
public Student findStudentById(int id) {
return studentDao.findStudentById(id);
}

@Override
public void updateStudent(Student student) {
studentDao.updateStudent(student);
}

@Override
public void deleteStudentById(int id) {
studentDao.deleteStudentById(id);
}

@Override
public void deleteSelectedStudent(int[] uid) {
for (int id : uid) {
studentDao.deleteStudentById(id);
}
}

@Override
public List<Student> findStudentByPage(Student student) {
return studentDao.findStudentByPage(student);
}

}

user>>impl>>UserServiceImpl

package com.itheima.service.impl;

import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class UserServiceImpl implements UserService {

@Autowired
private UserDao userDao;

@Override
public void registerUser(String username, String password) {

userDao.registerUser(username,password);
}

@Override
public User findUsernameAndPassword(User user) {
return userDao.findUsernameAndPassword(user);
}
}

三.项目总结
整个学生信息管理系统就这样写完了…其实不算是很复杂…
因为之前也写过Servlet版的…
所以在使用SSM整合的时候…
其实Dao层很多代码非常的简洁.都是框架帮我们完成…
之前我们每个功能都需要写一个Servlet…
SpringMVC的话只需要写方法就好了…
使用注解开发效率也会很高…
我已经将源码放到我的码云上面
码云地址:https://gitee.com/gubingkun/ssm_student_manage.git

以上内容自己整理 如有不正确的地方 欢迎批评指正~

Java笔记-坤坤

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: