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工程
2、引入项目依赖的jar包
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qroxy</groupId>
<artifactId>ssm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<!-- 引入项目依赖包 -->
<!-- springMVC -->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--spring-Jdbc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- spring 面向切面编程 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.7.RELEASE</version>
<!--mybatis-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mybtis整合适配包 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- springTest -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- 数据库连接池-->
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- mysql 驱动包 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!-- web工程标配包(jstl,servlet-api,junit) -->
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!-- scop标签作用:服务器已经有 -->
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependency>
</dependencies>
</project>
二、引入bootstrap前端框架
为了快速搭建前端页面,使用了bootstrap框架。在WEB-INF下新建一个static文件夹存放bootstrap和js。
三、编写SSM整合的关键配置文件
1、首先是web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!--1、启动Spring的容器 applicationContext.xml为spring配置文件 -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--2、springmvc的前端控制器,拦截所有请求 -->
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 3、字符编码过滤器,一定要放在所有过滤器之前 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 4、使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求 -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HttpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
需要注意的是使用rest风格uri时需要添加一个拦截PUT的拦截器,具体实现看HttpPutFormContentFilter这个类。
2、spring核心配置文件
该文件需放在resource下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:component-scan base-package="com.qroxy">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- ============Spring的配置文件,这里要配置和业务逻辑相关的bean -->
<!-- 数据源,事务控制xxx -->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.password}"></property>
<property name="password" value="${jdbc.user}"></property>
</bean>
<!--================== 配置和MyBatis的整合=============== -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="pooledDataSource"></property>
<!-- 指定mybatis,mapper文件的位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
<!-- 配置扫描器,将mybatis接口的实现加入ioc容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描dao接口实现,加入ioc容器中 -->
<property name="basePackage" value="com.qroxy.crud.dao"></property>
</bean>
<!-- 配置一个可以批量的sqlsession-->
<bean id="SqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" ></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
<!-- ========事务控制配置 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 控制住数据源 -->
<property name="dataSource" ref="pooledDataSource"></property>
</bean>
<!--开启基于注解的事务,使用xml形式的事务(主要使用配置xml方式) -->
<aop:config>
<!-- 切入点表达式,双点表示子包也能扫描得到,括号里面表示事务任意多 -->
<aop:pointcut expression="execution(* com.qroxy.crud.service..*(..))" id="txPoint"/>
<!-- 配置事务增强 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
</aop:config>
<!-- 配置事务增强 ,如何启动-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 所有方法都是事务方法 -->
<tx:method name="*"/>
<!-- 以get开头的所有方法 -->
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- Spring配置文件的核心点(数据源,与mybatis的整合,事务控制) -->
</beans>
主要是对事务和mybatis整合的配置,其中:
<!-- 配置一个可以批量的sqlsession-->
<bean id="SqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" ></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
只是用来批量生成数据的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配置文件位置一致
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.qroxy.crud.bean"/>
</typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 分页合理化参数,避免出现页数为负或者超过总页数-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
4、SpringMVC文件的配置
该文件放在WEB_IN目录下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- springMVC的配置文件,包括网站跳转逻辑的控制,配置 -->
<context:component-scan base-package="com.qroxy" use-default-filters="false">
<!-- 只扫描控制器 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 配置视图解析器 方便页面返回 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 两个标准配置 -->
<!--将springMVC不能处理的请求交给tomcat -->
<mvc:default-servlet-handler/>
<!-- 支持springMVC更高级的一些功能,JSR303校验,快捷ajax,映射动态请求-->
<mvc:annotation-driven/>
</beans>
以上就是对SSM的一个初步整合,要对员工数据进行增删改查还得需要使用mybatis的逆向工程生成对应的bean以 及mapper。
四、mybatis的逆向工程
可去mybatis官网看下相关文档,根据需要配置。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 配置数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm_crud" userId="root"
password="123456">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 指定javaBean生成的位置 -->
<javaModelGenerator targetPackage="com.atguigu.crud.bean"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--指定sql映射文件生成的位置 -->
<sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 指定dao接口生成的位置,mapper接口 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atguigu.crud.dao" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- table指定每个表的生成策略 -->
<table tableName="tbl_emp" domainObjectName="Employee"></table>
<table tableName="tbl_dept" domainObjectName="Department"></table>
</context>
</generatorConfiguration>
运行配置文件,官方提供了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<String> warnings = new ArrayList<String>();
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等文件。
五、用传统的方式做一个简单的查询
具体实现过程:
• 1、访问index.jsp页面
项目运行进入首页
• 2、index.jsp页面发送出查询员工列表请求
在inde.jsp页面做一个跳转:
<jsp:forward page="/emps"></jsp:forward>
• 3、EmployeeController来接受请求,查出员工数据
简单写一个控制器:
@RequestMapping("/emps")
public String getEmps(@RequestParam(value = "pn", defaultValue = "1") Integer pn,Model model){
// 这不是一个分页查询
// 引入PageHelper插件
// 在查询之前只需要调用,传入页码以及页码大小
PageHelper.startPage(pn, 10);
// startPage后面紧跟的这个查询就是分页查询
List<Employee> emps = employeeService.getAll();
// 使用pageInfo包装查询结果,只需要把pageInfo交给页面就行
// 封装了详细的分页信息,包括查询出来数据,连续显示的页数譬如5
PageInfo page = new PageInfo(emps,5);
model.addAttribute("PageInfo",page);
return "list";
}
因为要做分页处理,还得引入PageHelper相关依赖,并进行配置。
依赖
!--引入PageHelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
并在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" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>员工列表</title>
<%
pageContext.setAttribute("APP_PATH", request.getContextPath());
%>
<!-- web路径,不以/开始的相对路径,找资源,以当前路径为标准,经常出问题
以/开始的相对路径。找资源,以服务器路径为准,需要加上项目名
http://localhost:3306/crud
-->
<script src="${ APP_PATH}/static/js/jquery-1.12.4.min.js"></script>
<!-- 引入Bootstrap样式 -->
<link
href="${ APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"
rel="stylesheet">
<!-- 引入Bootstrapjs
-->
<script
src="${ APP_PATH}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<!-- 显示页面-->
<div class="container">
<!--标题 -->
<div class="row">
<div class=".col-md-12">
<h1>SSM_CRUD</h1>
</div>
</div>
<!--按钮 -->
<div class="row">
<div class="col-md-2 col-md-offset-10">
<button class="btn btn-primary btn-sm">新增</button>
<button class="btn btn-danger btn-sm">删除</button>
</div>
</div>
<!-- 显示数据 -->
<div class="row">
<div class="col-md-12">
<table class="table table-hover">
<tr>
<th>#</th>
<th>empName</th>
<th>gender</th>
<th>email</th>
<th>deptName</th>
<th>操作</th>
</tr>
<c:forEach items="${PageInfo.list }" var="emp">
<tr>
<th>${emp.empId }</th>
<th>${emp.empName }</th>
<th>${emp.gender=="M"?"男":"女" }</th>
<th>${emp.email }</th>
<th>${emp.department.deptName }</th>
<th>
<button class="btn-primary btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>编辑
</button>
<button class="btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>删除
</button>
</th>
</tr>
</c:forEach>
</table>
</div>
</div>
<!-- 显示分页信息栏 -->
<div class="row">
<!-- 分页文字信息 -->
<div class="col-md-6">
当前第${PageInfo.pageNum }页,总${PageInfo.pages }页,总${PageInfo.total }记录
</div>
<div class="col-md-6">
<nav aria-label="Page navigation">
<ul class="pagination">
<li><a href="${APP_PATH }/emps?pn=1">首页</a></li>
<c:if test="${PageInfo.hasPreviousPage }">
<li><a href="${ APP_PATH}/emps?pn=${PageInfo.pageNum-1}" aria-label="Previous"> <span
aria-hidden="true">«</span>
</a></li>
</c:if>
<c:forEach items="${PageInfo.navigatepageNums }" var="page_Num">
<c:if test="${page_Num==PageInfo.pageNum }">
<li class="active"><a href="#">${page_Num}</a></li>
</c:if>
<c:if test="${page_Num!=PageInfo.pageNum }">
<li><a href="${ APP_PATH}/emps?pn=${page_Num}">${page_Num}</a></li>
</c:if>
</c:forEach>
<c:if test="${PageInfo.hasNextPage }">
<li><a href="${ APP_PATH}/emps?pn=${PageInfo.pageNum+1}" aria-label="Next"> <span
aria-hidden="true">»</span>
</a></li>
</c:if>
<li><a href="${APP_PATH }/emps?pn=${PageInfo.pages}">末页</a></li>
</ul>
</nav>
</div>
</div>
</div>
</body>
</html>
• 5、pageHelper分页插件完成分页查询功能
六、利用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 = $("<td></td>").append(item.empId);
var empIdNameTd = $("<td></td>").append(item.empName);
var genderTd = $("<td></td>").append(
item.gender == 'M' ? "男" : "女");
var emailTd = $("<td></td>").append(item.email);
var departmentTd = $("<td></td>").append(
item.department.deptName);
var editBtn = $("<button></button>").addClass(
"btn-primary btn-sm btn_edit").attr("id","btn_edit").append(
$("<span></span>").addClass(
"glyphicon glyphicon-pencil")).append("编辑");
//添加一个属性value是id值
editBtn.attr("edit_id",item.empId);
var deletBtn = $("<button></button>").addClass(
"btn-danger btn-sm").attr("id","btn_delet").append(
$("<span></span>")
.addClass("glyphicon glyphicon-trash")).append(
"删除");
deletBtn.attr("delet_id",item.empId);
var butnTd = $("<td></td>").append(editBtn).add(deletBtn);
/* append方法执行完成以后还是返回原来的元素*/
$("<tr></tr>").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 = $("<ul></ul>").addClass("pagination");
//构建元素
var firstPage = $("<li></li>").append(
$("<a></a>").append("首页").attr("href", "#"));
var prePage = $("<li></li>").append($("<a></a>").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 = $("<li></li>")
.append($("<a></a>").append("»"));
var lastPage = $("<li></li>").append(
$("<a></a>").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 = $("<li></li>").append($("<a></a>").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 = $("<nav></nav>").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包
<!-- 引入json包 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
java实现:
/*
* 用responseBody生成json数据,必须先导入jackson包
*/
@RequestMapping("/emps")
@ResponseBody
public Msg getEmpWithJson(@RequestParam(value = "pn", defaultValue = "1") Integer pn) {
// 这不是一个分页查询
// 引入PageHelper插件
// 在查询之前只需要调用,传入页码以及页码大小
PageHelper.startPage(pn, 10);
// startPage后面紧跟的这个查询就是分页查询
List<Employee> 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、后端校验
当有人改了前端判断依据时,前端校验规则就会失效,此时就需要后端对数据重复校验。
引入校验依赖
<!-- 支持数据校验JSR303,tomcat7以上的服务器直接导入,以下的服务器:el表达式不是新标准lib中替换新标准-->
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.7.Final</version>
</dependency>
并在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
完成项目后,就是部署项目项目。操作如下:
成功后就会看到war包:
复杂粘贴到tomcat的webapp目录下启动,就会生成对应的目录。
打开目录会发现maven已经把所有需要的依赖都打包好了。
然后也可以访问到该服务器,此时已经不是镜像服务器了,而是实际服务器了。
九、总结
本次学习过程让我觉得对Spring实现原理的理解非常重要,SSM最让新手畏惧就是其繁琐的配置,在本次学习过程出现错误最多都是跟配置文件配置有关,且如果对SSM它的实现过程没有一个比较清晰的理解的话,即使出现错误也不能找出原因。做数据处理的时候也经常出错,这个原因是因为对jquery还不够熟悉,因此接下来对juquery和javascript的学习也是尤为重要。