SSM强化学习:从零到部署

SSM强化学习:从零到部署

本次是一次对SSM高级整合的练手,主要加强基本使用SSM做增删改查操作。项目内容是对员工数据的增删改查。

在项目开始之前先建两张表分别为员工表Employee和部门表dept:

-- ----------------------------
-- Table structure for tbl_dept
-- ----------------------------
DROP TABLE IF EXISTS `tbl_dept`;
CREATE TABLE `tbl_dept` (
  `deot_id` int(11) NOT NULL AUTO_INCREMENT,
  `dept_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  PRIMARY KEY (`deot_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Table structure for tbl_emp
-- ----------------------------
DROP TABLE IF EXISTS `tbl_emp`;
CREATE TABLE `tbl_emp` (
  `emp_id` int(11) NOT NULL AUTO_INCREMENT,
  `emp_name` varchar(235) NOT NULL,
  `gender` char(1) DEFAULT NULL,
  `emil` varchar(255) DEFAULT NULL,
  `d_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`emp_id`),
  KEY `fk_emp_deptt` (`d_id`),
  CONSTRAINT `fk_emp_dept` FOREIGN KEY (`d_id`) REFERENCES `tbl_dept` (`deot_id`),
  CONSTRAINT `fk_emp_deptt` FOREIGN KEY (`d_id`) REFERENCES `tbl_dept` (`deot_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

SET FOREIGN_KEY_CHECKS = 1;

一、基础环境的搭建

1、创建一个maven工程

SSM强化学习:从零到部署_第1张图片
image.png

2、引入项目依赖的jar包


  4.0.0
  com.qroxy
  ssm
  0.0.1-SNAPSHOT
  war
  
  
  
  
  

    org.springframework
    spring-webmvc
    4.3.7.RELEASE

  
  

    org.springframework
    spring-jdbc
    4.3.7.RELEASE

    
    

    org.springframework
    spring-aspects
    4.3.7.RELEASE
    
    


    

    org.mybatis
    mybatis
    3.4.2

    
    

    org.mybatis
    mybatis-spring
    1.3.1

    



    org.springframework
    spring-test
    4.3.7.RELEASE
    test


    
    

    c3p0
    c3p0
    0.9.1.2

    
    

    mysql
    mysql-connector-java
    8.0.11




    jstl
    jstl
    1.2



    javax.servlet
    javax.servlet-api
    3.1.0
    
    provided



    junit
    junit
    4.12
    test




  

二、引入bootstrap前端框架

为了快速搭建前端页面,使用了bootstrap框架。在WEB-INF下新建一个static文件夹存放bootstrap和js。


image.png
SSM强化学习:从零到部署_第2张图片
image.png

三、编写SSM整合的关键配置文件

1、首先是web.xml



    
    
    
    
        contextConfigLocation
        classpath:applicationContext.xml
    

    
    
        org.springframework.web.context.ContextLoaderListener
    
    
    
    
    
        dispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        1
    

    
    
        dispatcherServlet
        /
    
    
    
    
        CharacterEncodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
        
            forceRequestEncoding
            true
        
        
            forceResponseEncoding
            true
        
    
    
        CharacterEncodingFilter
        /*
    
    
    
    
        HiddenHttpMethodFilter
        org.springframework.web.filter.HiddenHttpMethodFilter
    
    
        HiddenHttpMethodFilter
        /*
    
    
        HttpPutFormContentFilter
        org.springframework.web.filter.HttpPutFormContentFilter
    
    
        HttpPutFormContentFilter
        /*
    
    
    

需要注意的是使用rest风格uri时需要添加一个拦截PUT的拦截器,具体实现看HttpPutFormContentFilter这个类。

2、spring核心配置文件

该文件需放在resource下


















    
        
        
        
        
        
    



















        















主要是对事务和mybatis整合的配置,其中:






只是用来批量生成数据的sqlseesion。
在整合完成且逆向生成文件后,测试其实现方式如下:


EmployeeMapper mapper=SqlSession.getMapper(EmployeeMapper.class);
    for (int i = 0; i < 1000; i++) {
        String uuid=UUID.randomUUID().toString().substring(0, 5)+""+i;
        mapper.insertSelective(new Employee(null,   uuid, "W", uuid+"@qroxy.cn", 2));
    }

3、配置mybatis文件

文件位置与spring配置文件位置一致




    
        
    
    
    
        
    

    
        
        
    



4、SpringMVC文件的配置

该文件放在WEB_IN目录下





















以上就是对SSM的一个初步整合,要对员工数据进行增删改查还得需要使用mybatis的逆向工程生成对应的bean以 及mapper。

四、mybatis的逆向工程

可去mybatis官网看下相关文档,根据需要配置。





    
        
            
        
        
        
        

        
            
        

        
        
            
            
        

        
        
            
        

        
        
            
        


        
        

运行配置文件,官方提供了java文件运行和maven运行两种方式,这里采用java方式,在test包下新建一个类,点开Running MyBatis Generator选项,选择java运行模版如下:

package com.atguigu.crud.test;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class MBGTest {

    public static void main(String[] args) throws Exception {
        List warnings = new ArrayList();
        boolean overwrite = true;
        File configFile = new File("mbg.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                callback, warnings);
        myBatisGenerator.generate(null);
    }
}


右键运行就会生成对于javabean和xml等文件。


SSM强化学习:从零到部署_第3张图片
image.png

五、用传统的方式做一个简单的查询

具体实现过程:

• 1、访问index.jsp页面

项目运行进入首页

• 2、index.jsp页面发送出查询员工列表请求

在inde.jsp页面做一个跳转:

 

• 3、EmployeeController来接受请求,查出员工数据

简单写一个控制器:

@RequestMapping("/emps")
    public String getEmps(@RequestParam(value = "pn", defaultValue = "1") Integer pn,Model model){
        // 这不是一个分页查询
        // 引入PageHelper插件
        // 在查询之前只需要调用,传入页码以及页码大小
        PageHelper.startPage(pn, 10);
        // startPage后面紧跟的这个查询就是分页查询
    
        List emps = employeeService.getAll();
//      使用pageInfo包装查询结果,只需要把pageInfo交给页面就行
//          封装了详细的分页信息,包括查询出来数据,连续显示的页数譬如5
        PageInfo page = new PageInfo(emps,5);
        model.addAttribute("PageInfo",page);
        
        return "list";
    }

因为要做分页处理,还得引入PageHelper相关依赖,并进行配置。
依赖

!--引入PageHelper分页插件  -->

    com.github.pagehelper
    pagehelper
    5.0.0


并在mybatis配置文件做一个配置。(已配置)

• 4、来到list.jsp页面进行展示

在WEB_INF下新建一个views文件再里面建一个list.jsp文件:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>




员工列表
<%
    pageContext.setAttribute("APP_PATH", request.getContextPath());
%>








    
    

SSM_CRUD

# empName gender email deptName 操作
${emp.empId } ${emp.empName } ${emp.gender=="M"?"男":"女" } ${emp.email } ${emp.department.deptName }
当前第${PageInfo.pageNum }页,总${PageInfo.pages }页,总${PageInfo.total }记录

• 5、pageHelper分页插件完成分页查询功能

SSM强化学习:从零到部署_第4张图片
image.png

六、利用ajax来请求数据渲染前端页面

前面使用传统的渲染页面,不但效率差,还对服务器性能有影响,并且这种方式只能在浏览器实现,终端耦合高,而使用ajax来请求数据的话就相对来说没有以上的缺点或者影响更小。
主要实现过程如下(以查询员工为例):

•1、index.jsp页面直接发送ajax请求进行员工分页数据的查询

$(function() {
            //去首页
            to_page(1)
        });
        //抽离方法
        function to_page(pn) {
            $.ajax({
                url : "${APP_PATH}/emps",
                data : "pn=" + pn,
                type : "GET",
                success : function(result) {
                    //console.log(result)
                    //1、解析并显示员工数据
                    build_emps_table(result);
                    //2、解析并显示分页信息
                    build_page_info(result);
                    //3、解析分页条信息
                    build_page_nav(result);
                }
            });
        }
        function build_emps_table(result) {
            //请空表格
            $("#emps_tables tbody").empty();
            var emps = result.extend.PageInfo.list;
            $.each(emps, function(index, item) {
                var empIdTd = $("").append(item.empId);
                var empIdNameTd = $("").append(item.empName);
                var genderTd = $("").append(
                        item.gender == 'M' ? "男" : "女");
                var emailTd = $("").append(item.email);
                var departmentTd = $("").append(
                        item.department.deptName);
                var editBtn = $("").addClass(
                        "btn-primary btn-sm btn_edit").attr("id","btn_edit").append(
                        $("").addClass(
                                "glyphicon glyphicon-pencil")).append("编辑");
                //添加一个属性value是id值
                editBtn.attr("edit_id",item.empId);
                var deletBtn = $("").addClass(
                        "btn-danger btn-sm").attr("id","btn_delet").append(
                        $("")
                                .addClass("glyphicon glyphicon-trash")).append(
                        "删除");
                deletBtn.attr("delet_id",item.empId);
                var butnTd = $("").append(editBtn).add(deletBtn);
                /*  append方法执行完成以后还是返回原来的元素*/
                $("").append(empIdTd).append(empIdNameTd).append(
                        empIdNameTd).append(genderTd).append(emailTd)

                .append(departmentTd).append(butnTd)

                .appendTo("#emps_tables tbody");

            })
        }
        //解析显示分页信息
        function build_page_info(result) {
            $("#page_info").empty();
            $("#page_info").append(
                    "当前第" + result.extend.PageInfo.pageNum + "页,总"
                            + result.extend.PageInfo.pages + "页,总"
                            + result.extend.PageInfo.total + "条记录")
                            currentPage=result.extend.PageInfo.pageNum;
        }
        //解析显示分条信息,点击分页有跳转动作

        function build_page_nav(result) {
            $("#page_nav").empty();
            //page_nav
            var ul = $("
    ").addClass("pagination"); //构建元素 var firstPage = $("
  • ").append( $("").append("首页").attr("href", "#")); var prePage = $("
  • ").append($("").append("«")); if (result.extend.PageInfo.hasPreviousPage == false) { prePage.addClass("disabled"); firstPage.addClass("disabled"); } else { //首页 firstPage.click(function() { to_page(1); }); //点击上一页跳转动作 prePage.click(function() { to_page(result.extend.PageInfo.pageNum - 1); }); } var nextPage = $("
  • ") .append($("").append("»")); var lastPage = $("
  • ").append( $("").append("末页").attr("href", "#")); if (result.extend.PageInfo.hasNextPage == false) { nextPage.addClass("disabled"); lastPage.addClass("disabled"); } else { //点击下一页跳转动作 nextPage.click(function() { to_page(result.extend.PageInfo.pageNum + 1); }); //末页 lastPage.click(function() { to_page(result.extend.PageInfo.pages); }); } ul.append(firstPage).append(prePage); //添加首页和前一页 //1,2,3,,4,5添加页码提示 $.each(result.extend.PageInfo.navigatepageNums, function(index, item) { var numLi = $("
  • ").append($("").append(item)); if (result.extend.PageInfo.pageNum == item) { numLi.addClass("active"); } //点击上一页跳转动作 numLi.click(function() { to_page(item); }); ul.append(numLi); }); //全部添加完后,再添加最后一页和下一页提示 ul.append(nextPage).append(lastPage); var navEle = $("").append(ul); navEle.appendTo("#page_nav"); numLi.click(function() { to_page(item); }); } function reset_form(ele){ $(ele)[0].reset(); //清空表单样式 $(ele).find("*").removeClass("has-error has-success"); $(ele).find(".help-block").text(""); }

    • 2、服务器将查出的数据,以json字符串的形式返回给浏览器

    要服务器能json的方式返回数据,还要引入json包

    
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.8.8
    
    

    java实现:

    /*
         * 用responseBody生成json数据,必须先导入jackson包
         */
        @RequestMapping("/emps")
        @ResponseBody
        public Msg getEmpWithJson(@RequestParam(value = "pn", defaultValue = "1") Integer pn) {
            // 这不是一个分页查询
                    // 引入PageHelper插件
                    // 在查询之前只需要调用,传入页码以及页码大小
                    PageHelper.startPage(pn, 10);
                    // startPage后面紧跟的这个查询就是分页查询
                
                    List emps = employeeService.getAll();
    //              使用pageInfo包装查询结果,只需要把pageInfo交给页面就行
    //                  封装了详细的分页信息,包括查询出来数据,连续显示的页数譬如5
                    PageInfo page = new PageInfo(emps,5);
                    return Msg.success().add("PageInfo", page);
        }
    

    • 3、浏览器收到js字符串。可以使用js对json进行解析,使用js通过 dom增删改改变页面。

    进而实现了实现客户端的无关性。

    七、数据校验

    在添加员工和修改员工时为了更好的交互体验和防止数据臃肿,必须对提交数据进行校验。

    1、前端校验

    利用正则表达式对提交数据校验,方法如下:

    function validate_add_from() {
                //1、拿到要校验的数据
                var empName = $("#empName_add").val();
                //数字字母中文
                var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
    
                //校验邮箱信息
                var email = $("#email").val();
                var regemail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
    
                if (regName.test(empName) == false) {
                    show_validate_msg("#empName_add", "error", "用户名不规则!!");
                    return false;
                } else {
                    show_validate_msg("#empName_add", "success", "");
                }
    
                if (regemail.test(email) == false) {
                    show_validate_msg("#email", "error", "邮箱格式不对!!");
    
                    return false;
                } else {
                    show_validate_msg("#email", "success", "");
    
                }
                return true;
            }
    

    2、后端校验

    当有人改了前端判断依据时,前端校验规则就会失效,此时就需要后端对数据重复校验。
    引入校验依赖

    
    
    
        org.hibernate.validator
        hibernate-validator
        6.0.7.Final
    
    

    并在SpringMVC配置文件做好相关配置。
    在Employee.java对相关需要校验的字段进行注解校验:

    ....
    //  JSR数据校验
      @Pattern(regexp="^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$",message="邮箱格式不对")
      private String email;
      
        @Pattern(regexp="(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})",message="用户名不规则")
        private String empName;
        ...
    

    在控制器中写一个校验接口:

    /*
         * 校验用户名是否可用
         */
        @RequestMapping("/checkuser")
        @ResponseBody
        
        public Msg checkUser(@RequestParam("empName")String empName) {
            //先判断用户名是否合法的
            String regx="(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})";
            if (!empName.matches(regx)) {
                return Msg.fail().add("va_msg", "用户名不规则");
            }
            boolean b= employeeService.checkUser(empName);
            if (b) {
                return Msg.success();
            }else {
                return Msg.fail().add("va_msg", "用户名不可用");
            }
        }
    

    其对应的service实现类中的方法:

    public Boolean checkUser(String empName) {
            EmployeeExample example = new EmployeeExample();
            Criteria criteria = example.createCriteria();
            criteria.andEmpNameEqualTo(empName);
            long count = mapper.countByExample(example);
            if (count == 0) {
                return true;
            } else {
                return false;
            }
        }
    

    八、生成war部署Tomcat

    完成项目后,就是部署项目项目。操作如下:


    SSM强化学习:从零到部署_第5张图片
    image.png

    成功后就会看到war包:


    SSM强化学习:从零到部署_第6张图片
    image.png

    复杂粘贴到tomcat的webapp目录下启动,就会生成对应的目录。
    image.png
    SSM强化学习:从零到部署_第7张图片
    image.png

    打开目录会发现maven已经把所有需要的依赖都打包好了。


    SSM强化学习:从零到部署_第8张图片
    image.png

    然后也可以访问到该服务器,此时已经不是镜像服务器了,而是实际服务器了。


    SSM强化学习:从零到部署_第9张图片
    image.png

    SSM强化学习:从零到部署_第10张图片
    image.png

    九、总结

    本次学习过程让我觉得对Spring实现原理的理解非常重要,SSM最让新手畏惧就是其繁琐的配置,在本次学习过程出现错误最多都是跟配置文件配置有关,且如果对SSM它的实现过程没有一个比较清晰的理解的话,即使出现错误也不能找出原因。做数据处理的时候也经常出错,这个原因是因为对jquery还不够熟悉,因此接下来对juquery和javascript的学习也是尤为重要。

    你可能感兴趣的:(SSM强化学习:从零到部署)