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

刚刚学习完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;
        }
        userService.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

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

  • 20
    点赞
  • 211
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值