前言
SSM学了这么长时间了,终于到了整合做项目的时候了,但是没想到实际遇到的问题比当时做JSP+Servlet的时候还要多,虽然都是跟着视频做(摊手),因为遇到的问题太多了,不得不写下这个文档(苦笑),说实话,我真的不想写这个文档,感觉太浪费时间了,但是为了自己以后的开发,更为了加深对这个SSM的印象,我还是写了,希望能有丶帮助吧!
开发环境
JDK1.8+Tomcat8.0+MySQL5.6+Maven
技术点
- 基础框架-SSM(Spring+SpringMVC+MyBatis)
- 前端框架-Bootstrap
- 分页-pagehelper
- 逆向工程-MyBatis Generator
实现功能
- 分页
- 数据校验 jquery前端校验+JSR303后端校验
- ajax
- Rest风格的URI;使用HTTP协议请求方式的动词,来表示对资源的操作(GET(查询),POST(新增),PUT(修改),DELETE(删除))
项目地址
GitHub:https://github.com/UnityAlvin/ssmbuild
项目搭建
基础配置
1.新建一个空的Maven项目
2.右键项目名添加Web支持
3.将web文件夹移动到src/main路径下
4.修改web文件夹的路径配置
后端底层配置
pom.xml
导入依赖的jar包
<?xml version="1.0" encoding="UTF-8"?>
<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.indi</groupId>
<artifactId>ssmcrud</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--pagehelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--mybatis逆向生成dao、xml、bean-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
<!--数据连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!--jackson插件返回json字符串的支持-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<!--JSR303数据校验支持-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--指定jdk版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
database.properties
数据库配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
mybatis-config.xml
<?xml version="1.0" encoding="GBK" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.indi.pojo"/>
</typeAliases>
<plugins>
<!--配置拦截器插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--分页参数合理化,避免出现小于第一页,大于最后一页的情况-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
spring-service.xml
<?xml version="1.0" encoding="GBK"?>
<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.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描service相关的bean -->
<context:component-scan base-package="com.indi.service" />
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- aop事务支持-->
<!--配置声明式事务-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--
配置事务的传播特性:
propagation-REQUIRED为spring的默认事务
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.indi.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
</beans>
spring-dao.xml
<?xml version="1.0" encoding="GBK"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置整合mybatis -->
<!-- 1.关联数据库文件 -->
<context:property-placeholder location="classpath:database.properties"/>
<!-- 2.数据库连接池 -->
<!--数据库连接池
dbcp 半自动化操作 不能自动连接
c3p0 自动化操作(自动的加载配置文件 并且设置到对象里面)
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接池属性 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 3.配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 如果-->
<property name="mapperLocations" value="classpath*:/mapper/*.xml"/>
</bean>
<!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.indi.dao"/>
</bean>
<!--配置一个可以批量插入的sqlSession-->
<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSession">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
</beans>
spring-mvc.xml
<?xml version="1.0" encoding="GBK"?>
<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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解驱动,以支持SpringMVC更高级的功能 -->
<mvc:annotation-driven />
<!-- 2.将springmvc不能处理的请求交给tomcat,以实现静态动态资源都可以访问-->
<mvc:default-servlet-handler/>
<!-- 3.配置jsp 显示ViewResolver视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.indi.controller" />
</beans>
applicationContext.xml
整合了Spring的三个文件
<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:spring-dao.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="classpath:spring-mvc.xml"/>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--DispatcherServlet-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--过滤器encodingFilter-->
<filter>
<filter-name>encodingFilter</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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--使用restful风格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>FormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Session过期时间-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
mybatis逆向工程
可以自动生成对应的bean以及mapper文件
pom.xml
<!--mybatis逆向生成dao、xml、bean-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
mbg.xml
<?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/ssmbuild"
userId="root"
password="123456">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--指定JavaBean生成的位置-->
<javaModelGenerator targetPackage="com.indi.pojo" 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接口生成位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.indi.dao" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--指定每个表的生成策略-->
<!-- <table tableName="t_emp" domainObjectName="Employee"></table>
<table tableName="t_dept" domainObjectName="Department"></table>-->
<table tableName="t_user" domainObjectName="User"></table>
</context>
</generatorConfiguration>
MBGTest.java
package com.indi.test;
/**
* mybatis生成dao、bean、mapper文件
*/
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);
}
}
修改Mapper文件
这里是因为查询员工信息的同时,还需要查询部门信息,用到了连表查询,所以修改了Mapper文件
EmployeeMapper.xml
<!--新增Map-->
<resultMap id="WithDeptResultMap" type="com.indi.pojo.Employee">
<id column="emp_id" jdbcType="INTEGER" property="empId"/>
<result column="emp_name" jdbcType="VARCHAR" property="empName"/>
<result column="gender" jdbcType="CHAR" property="gender"/>
<result column="email" jdbcType="VARCHAR" property="email"/>
<result column="d_id" jdbcType="INTEGER" property="dId"/>
<!--联合查询的部门字段封装-->
<association property="department" javaType="com.indi.pojo.Department">
<id column="dept_id" property="deptId"/>
<id column="dept_name" property="deptName"/>
</association>
</resultMap>
<!--新增查询部门信息的字段-->
<sql id="WithDept_Column_List">
e.emp_id, e.emp_name, e.gender, e.email, e.d_id, d.dept_id, d.dept_name
</sql>
<!--新增查询员工时同时查询部门信息-->
<!--按条件查询-->
<select id="selectByExampleWithDept" resultMap="WithDeptResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="WithDept_Column_List"/>
from t_emp e
left join t_dept d on e.d_id = d.dept_id
<if test="_parameter != null">
<include refid="Example_Where_Clause"/>
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
<if test="orderByClause == null">
order by e.emp_id
</if>
</select>
<!--按主键查询-->
<select id="selectByPrimaryKeyWithDept" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="WithDept_Column_List"/>
from t_emp e
left join t_dept d on e.d_id = d.dept_id
where emp_id = #{empId,jdbcType=INTEGER}
</select>
简化实体类
Department.java
package com.indi.pojo;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Department {
private Integer deptId;
private String deptName;
}
Employee.java
package com.indi.pojo;
@Data
@NoArgsConstructor
public class Employee {
private Integer empId;
private String empName;
private String gender;
private String email;
private Integer dId;
//查询员工的同时查询部门信息
private Department department;
public Employee(Integer empId, String empName, String gender, String email, Integer dId) {
this.empId = empId;
this.empName = empName;
this.gender = gender;
this.email = email;
this.dId = dId;
}
}
User.java
package com.indi.pojo;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
}
搭建Spring测试环境
使用Spring的测试模块测试数据
pom.xml
<!--Spring的测试模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
MapperTest.java
package com.indi.test;
/**
* 测试dao层
* 使用Spring的单元测试,可以自动注入需要的组件
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class MapperTest {
@Autowired
DepartmentMapper departmentMapper;
@Autowired
EmployeeMapper employeeMapper;
@Autowired
UserMapper userMapper;
@Autowired
SqlSession sqlSession;
@Test
/**
* 测试添加数据
*/
public void test() {
//插入几个部门
// departmentMapper.insertSelective(new Department(null,"d1部"));
// departmentMapper.insertSelective(new Department(null,"d2部"));
//生成员工数据
// employeeMapper.insertSelective(new Employee(null,"Jerry3","M","Jerry3@qq.com",1));
//批量插入多个员工
// EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
// for (int i = 0; i < 10; i++) {
// String uid = UUID.randomUUID().toString().substring(0, 5) + i;
// mapper.insertSelective(new Employee(null, uid, "M", uid + "@qq.com", 1));
// }
// System.out.println("批量完成");
}
登录
只有管理员账户可以登录
此处遇到了一点问题,因为我是直接从之前写完的项目往一个新项目里拷贝的,所以出现了一些莫名其妙的报错,后来发现在idea中移动几次位置,或者先创建出同名文件,再把代码复制粘贴上就没问题了。
web目录
前端
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<jsp:forward page="/login"></jsp:forward>
head.jsp
配置前端需要用的框架、样式、项目路径
<%--
web路径:
不以/开始的相对路径,是从当前目录为基准进行查找,经常出问题
以/开始的路径,则是从服务器的路径为基准开始查找,但是需要加上项目名
--%>
<%
pageContext.setAttribute("HTTP_PATH", request.getContextPath());
%>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
pageContext.setAttribute("HTTP_PATH", request.getContextPath());
%>
<html>
<head>
<title>登录</title>
<%@include file="common/head.jsp" %>
<script type="text/javascript">
if ("${msg}" != "") {
alert("${msg}")
}
</script>
</head>
<body>
<div class="container">
<div class="row">
<div class="page-header">
<h1>员工管理系统</h1>
</div>
</div>
<div class="row">
<form method="post" action="${HTTP_PATH}/goLogin" class="form-horizontal">
<div class="form-group">
<label for="exampleInputName3" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-5">
<input type="text" name="username" class="form-control" id="exampleInputName3" placeholder="用户名">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">密码</label>
<div class="col-sm-5">
<input type="password" name="password" class="form-control" id="inputPassword3" placeholder="密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> 记住密码
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">登录</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>
后端
UserMapper.xml
<!--新增根据用户名、密码查询账户是否存在-->
<select id="selectByUsernameAndPassword" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_user
where username=#{username, jdbcType=INTEGER}
and password=#{password,jdbcType=INTEGER}
</select>
UserService.java
package com.indi.service;
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public User getUserByUsernameAndPassword(String username, String password) {
return userMapper.selectByUsernameAndPassword(username, password);
}
}
UserMapper.java
package com.indi.dao;
public interface UserMapper {
//新增的查询方法
User selectByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
}
UserController.java
package com.indi.controller;
@Controller
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/login")
public String login() {
return "login";
}
}
测试分页
使用Spring测试模块的测试请求功能
pom.xml
<!--pagehelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
mybatis-config.xml
放在<typeAliases>标签后面
<plugins>
<!--配置拦截器插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--分页参数合理化,避免出现小于第一页,大于最后一页的情况-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
EmployeeMapper.java
package com.indi.dao;
public interface EmployeeMapper {
//新增
List<Employee> selectByExampleWithDept(EmployeeExample example);
//新增
Employee selectByPrimaryKeyWithDept(Integer empId);
}
EmployeeService.java
package com.indi.service;
@Service
public class EmployeeService {
/**
* 查询所有员工
*/
@Autowired
EmployeeMapper employeeMapper;
public List<Employee> getAll() {
//引入分页插件PageHelper
return employeeMapper.selectByExampleWithDept(null);
}
}
EmployeeController.java
package com.indi.controller;
public class EmployeeController {
@Autowired
EmployeeService employeeService;
/**
* 查询员工数据
* @return
*/
@RequestMapping("/emps")
public String getEmps(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model){
//在查询之前只需要调用此方法,传入页码,以及每页的个数即可
PageHelper.startPage(pn,5);
List<Employee> emps = employeeService.getAll();
//使用pageInfo包装查询后的结果,只需要将pageInfo传回页面即可
//封装了详细的分页信息,包括查询出来的数据,传入5表示连续显示的页数
PageInfo page = new PageInfo(emps,5);
model.addAttribute("pageInfo",page);
return "list";
}
}
MvcTest.java
package com.indi.test;
/**
* 使用Spring测试模块的测试请求功能,测试CRUD请求的正确性
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class MvcTest {
//传入SpringMVC的ioc
@Autowired
WebApplicationContext context;
//虚拟mvc请求,获取到处理结果
MockMvc mockMvc;
@Before
public void initMockMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testPage() throws Exception {
//模拟请求拿到返回值
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pn", "5")).andReturn();
//请求成功之后,请求域中会有pageinfo,可以去除pageinfo进行验证
MockHttpServletRequest request = result.getRequest();
PageInfo pi = (PageInfo) request.getAttribute("pageInfo");
System.out.println(pi);
System.out.println("当前页码:" + pi.getPageNum());
System.out.println("总页码:" + pi.getPages());
System.out.println("总记录数:" + pi.getTotal());
System.out.println("在页面需要连续显示的页码");
int[] nums = pi.getNavigatepageNums();
for (int i : nums) {
System.out.println(" " + i);
}
//获取员工数据
List<Employee> list = pi.getList();
for (Employee employee : list) {
System.out.println("ID" + employee.getEmpId() + "Name" + employee.getEmpName());
}
}
}
显示分页数据
前端
list.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: New
Date: 2020/6/1
Time: 23:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>员工展示</title>
<%@include file="common/head.jsp" %>
</head>
<body>
<div class="container">
<%--清除浮动--%>
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>员工列表</h1>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<form action="" method="" class="form-inline">
<input type="text" placeholder="请输入要查询的员工名称" class="form-control" name="empName">
<button class="btn btn-primary">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
查询
</button>
</form>
</div>
<div class="col-md-4 column">
</div>
<div class="col-md-4 column" align="right">
<button class="btn btn-primary">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
新增
</button>
<button class="btn btn-danger">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
删除
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>员工名称</th>
<th>性别</th>
<th>邮箱</th>
<th>部门</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${pageInfo.list}" var="emp">
<tr>
<td>${emp.empId}</td>
<td>${emp.empName}</td>
<td>${emp.gender=="M"?"男":"女"}</td>
<td>${emp.email}</td>
<td>${emp.department.deptName}</td>
<td>
<button class="btn btn-primary btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
编辑
</button>
<button class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
删除
</button>
</td>
</tr>
</c:forEach>
</tbody>
</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">
<%--设置首页、上一页按钮状态--%>
<c:if test="${pageInfo.hasPreviousPage}">
<li><a href="${HTTP_PATH}/emps?pn=1">首页</a></li>
<li>
<a href="${HTTP_PATH}/emps?pn=${pageInfo.pageNum-1}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
</c:if>
<c:if test="${!pageInfo.hasPreviousPage}">
<li class="disabled"><span>首页</span></li>
<li class="disabled">
<span aria-hidden="true">«</span>
</li>
</c:if>
<%--设置当前页按钮的状态--%>
<c:forEach items="${pageInfo.navigatepageNums}" var="page_Num">
<c:if test="${page_Num == pageInfo.pageNum}">
<li class="active"><span>${page_Num}</span></li>
</c:if>
<c:if test="${page_Num != pageInfo.pageNum}">
<li><a href="${HTTP_PATH}/emps?pn=${page_Num}">${page_Num}</a></li>
</c:if>
</c:forEach>
<%--设置末页、下一页按钮状态--%>
<c:if test="${pageInfo.hasNextPage}">
<li>
<a href="${HTTP_PATH}/emps?pn=${pageInfo.pageNum + 1}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
<li><a href="${HTTP_PATH}/emps?pn=${pageInfo.pages}">末页</a></li>
</c:if>
<c:if test="${!pageInfo.hasNextPage}">
<li class="disabled">
<span aria-hidden="true">»</span>
</li>
<li class="disabled"><span>末页</span></li>
</c:if>
</ul>
</nav>
</div>
</div>
</div>
</body>
</html>
后端
UserController.java
添加登录之后页面跳转逻辑
package com.indi.controller;
@Controller
public class UserController {
@RequestMapping("/goLogin")
public String goLogin(HttpSession session, String username, String password, Model model) {
User user = userService.getUserByUsernameAndPassword(username, password);
if (user == null) {
model.addAttribute("msg","用户名或密码错误");
return "login";
} else {
session.setAttribute("user", user);
return "redirect:/emps";
}
}
}