SpringMVC 中 Interceptor 拦截器的主要作⽤是拦截⽤⼾的请求并进⾏相应的处理。⽐如通过它来进⾏权限验证,或者是来判断⽤⼾是否登陆等操作。对于 SpringMVC 拦截器的定义⽅式有两种:
实现接⼝:org.springframework.web.servlet.HandlerInterceptor
继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter
/**
* 拦截器的实现
* 实现 HandlerInterceptor 接口
*/
public class MyInterceptor01 implements HandlerInterceptor {
/**
* 在目标Handler(方法)执行前执行
* 返回true:执行Handler方法
* 返回false:阻止目标Handler执行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("目标Handler执行前执行MyInterceptor01 --> preHandle方法...");
/**
* 返回true:执行Handler方法
* 返回false:阻止目标Handler执行
*/
return true;
}
/**
* 在 目标Handler(方法)执行后,视图生成前 执行
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("目标Handler执行后,视图生成前执行MyInterceptor01 --> postHandle方法...");
}
/**
* 在 目标Handler(方法)执行后,视图生成后 执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("目标Handler执行后,视图生成后执行MyInterceptor01 --> afterCompletion方法...");
}
}
<mvc:interceptors>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/>
mvc:interceptors>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/url/*"/>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/>
mvc:interceptor>
mvc:interceptors>
实际上最终还是 HandlerInterceptor 接⼝实现。
/**
* 拦截器实现
* 继承 HandlerInterceptorAdapter 适配器
*/
public class MyInterceptor02 extends HandlerInterceptorAdapter {
/**
* 在 目标Handler(方法)执行前 执行
* 返回true:执行Handler方法
* 返回false:阻止目标Handler执行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("目标Handler执行前执行MyInterceptor02 --> preHandle方法...");
return true;
}
/**
* 在 目标Handler(方法)执行后,视图生成前 执行
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("目标Handler执行后,视图生成前执行MyInterceptor02 --> postHandle方法...");
}
/**
* 在 目标Handler(方法)执行后,视图生成后 执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("目标Handler执行后,视图生成后执行MyInterceptor02 --> afterCompletion方法...");
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/url/test01"/>
<mvc:exclude-mapping path="/url/test02"/>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02"/>
mvc:interceptor>
mvc:interceptors>
SpringMVC 框架⽀持多个拦截器配置,从⽽构成拦截器链,对客⼾端请求进⾏多次拦截操作。
这⾥参考MyInterceptor01、MyInterceptor02代码
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02"/>
mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/>
mvc:interceptor>
mvc:interceptors>
使⽤拦截器完成⽤⼾是否登录请求验证功能
UserInfoController 定义
/**
* 用户模块
* 用户登录 (不需要拦截)
* 用户添加 (需要拦截)
* 用户更新 (需要拦截)
* 用户删除 (需要拦截)
*/
@Controller
@RequestMapping("/userInfo")
public class UserInfoController {
/**
* 用户登录
* @return
*/
@RequestMapping("/login")
public ModelAndView userLogin(HttpSession session){
System.out.println("用户登录...");
ModelAndView modelAndView = new ModelAndView();
// 设置视图
modelAndView.setViewName("success");
// 如果用户登录,则设置用户对象到session作用域中
User user = new User();
user.setId(1);
user.setUserName("admin");
user.setUserPwd("123456");
session.setAttribute("user", user);
return modelAndView;
}
/**
* 用户添加
* @return
*/
@RequestMapping("/add")
public ModelAndView userAdd(){
System.out.println("用户添加...");
ModelAndView modelAndView = new ModelAndView();
// 设置视图
modelAndView.setViewName("success");
return modelAndView;
}
/**
* 用户更新
* @return
*/
@RequestMapping("/update")
public ModelAndView userupdate(){
System.out.println("用户更新...");
ModelAndView modelAndView = new ModelAndView();
// 设置视图
modelAndView.setViewName("success");
return modelAndView;
}
/**
* 用户删除
* @return
*/
@RequestMapping("/delete")
public ModelAndView userDelete(){
System.out.println("用户删除...");
ModelAndView modelAndView = new ModelAndView();
// 设置视图
modelAndView.setViewName("success");
return modelAndView;
}
}
success.jsp 定义
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登录页面
LoginInterceptor 定义
public class LoginInterceptor extends HandlerInterceptorAdapter {
/**
* 在 目标方法执行前 执行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取session作用域中的user对象
User user = (User) request.getSession().getAttribute("user");
// 判断session作用域的user对象是否为空
if (user == null){ // 如果为空,表示用户未登录
// 拦截请求并跳转到登录页面
response.sendRedirect(request.getContextPath() + "/login.jsp");
// 不执行目标方法
return false;
}
// 执行目标方法
return true;
}
}
servlet-context.xml 配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/userInfo/login"/>
<mvc:exclude-mapping path="/uploadFile"/>
<mvc:exclude-mapping path="/uploadFiles"/>
<bean class="com.xxxx.springmvc.interceptor.LoginInterceptor"/>
mvc:interceptor>
mvc:interceptors>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.2version>
dependency>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>104857600value>
property>
<property name="maxInMemorySize">
<value>4096value>
property>
bean>
input 的type设置为file
form 表单的method设为post
form 表单的enctype设置为multipart/form-data,以⼆进制的形式传输数据
/**
* 单文件上传
*
* @return
*/
@Controller
public class FileController {
@RequestMapping("/uploadFile")
public String uploadFile(HttpServletRequest request, @RequestParam("file") MultipartFile file) {
// 判断文件是否为空,如果不为空则进行对应的文件上传操作
if (!file.isEmpty()) {
try {
// 获取项目所在的路径 (绝对路径)
String path = request.getServletContext().getRealPath("/");
// 设置上传文件存放的目录
File uploadFile = new File(path + "/upload");
// 判断文件目录是否存在,如果不存在则新建对应的目录
if (!uploadFile.exists()) {
// 新建目录
uploadFile.mkdir();
}
// 获取上传文件的文件名
String originalName = file.getOriginalFilename();
// 获取上传文件的后缀名
String suffix = originalName.substring(originalName.lastIndexOf("."));
// 通过系统当前时间的毫秒数,生成随机的文件名
String fileName = System.currentTimeMillis() + suffix;
// 上传文件 (转存文件到指定目录)
file.transferTo(new File(uploadFile, fileName));
// 如果上传成功,设置作用域
request.setAttribute("msg", "文件上传成功!");
} catch (IOException e) {
e.printStackTrace();
// 如果上传失败,设置作用域
request.setAttribute("msg", "文件上传失败!");
}
} else {
// 如果上传文件不存在,设置作用域
request.setAttribute("msg", "文件不存在!");
}
return "result";
}
}
<form method="post" action="uploadFiles" enctype="multipart/form-data">
<input type="file" name="files"/>
<input type="file" name="files"/>
<button>上传button>
form>
@RequestMapping("/uploadFiles")
public String uploadFiles(HttpServletRequest request, @RequestParam("files") List<MultipartFile> files){
// 判断文件集合是否为空
if (files != null && files.size() > 0) {
for (MultipartFile file : files ) {
// 上传文件
saveFile(file, request);
}
}
return "result";
}
/**
* 上传文件
* @param file
* @param request
*/
public void saveFile(MultipartFile file, HttpServletRequest request) {
// 判断文件是否为空,如果不为空则进行对应的文件上传操作
if (!file.isEmpty()) {
try {
// 获取项目所在的路径 (绝对路径)
String path = request.getServletContext().getRealPath("/");
// 设置上传文件存放的目录
File uploadFile = new File(path + "/upload");
// 判断文件目录是否存在,如果不存在则新建对应的目录
if (!uploadFile.exists()) {
// 新建目录
uploadFile.mkdir();
}
// 获取上传文件的文件名
String originalName = file.getOriginalFilename();
// 获取上传文件的后缀名
String suffix = originalName.substring(originalName.lastIndexOf("."));
// 通过系统当前时间的毫秒数,生成随机的文件名
String fileName = System.currentTimeMillis() + suffix;
// 上传文件 (转存文件到指定目录)
file.transferTo(new File(uploadFile, fileName));
// 如果上传成功,设置作用域
request.setAttribute("msg","文件上传成功!");
} catch (IOException e) {
e.printStackTrace();
// 如果上传失败,设置作用域
request.setAttribute("msg","文件上传失败!");
}
} else {
// 如果上传文件不存在,设置作用域
request.setAttribute("msg","文件不存在!");
}
}
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.5.2version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.3version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.3version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.19version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.2version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.1.10version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.10.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.10.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.10.0version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.2version>
dependency>
dependencies>
<build>
<finalName>ssmfinalName>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
<include>**/*.propertiesinclude>
<include>**/*.tldinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>2.3.2version>
<configuration>
<source>1.8source>
<target>1.8target>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.eclipse.jettygroupId>
<artifactId>jetty-maven-pluginartifactId>
<version>9.4.27.v20200227version>
<configuration>
<scanIntervalSeconds>10scanIntervalSeconds>
<httpConnector>
<port>8080port>
httpConnector>
<webAppConfig>
<contextPath>/ssmcontextPath>
webAppConfig>
configuration>
plugin>
plugins>
build>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<filter>
<description>char encoding filterdescription>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>springMvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:servlet-context.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springMvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.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.xsd">
<context:component-scan base-package="com.xxxx.ssm.controller" />
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
mvc:message-converters>
mvc:annotation-driven>
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>104857600value>
property>
<property name="maxInMemorySize">
<value>4096value>
property>
bean>
beans>
在项⽬的 src/main/resources 下创建 spring.xml ⽂件, 内容如下
<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
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.xxxx.ssm" >
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
context:component-scan>
<context:property-placeholder location="classpath:db.properties" />
<aop:aspectj-autoproxy />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}">property>
<property name="jdbcUrl" value="${jdbc.url}">property>
<property name="user" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="servicePointcut"
expression="execution(* com.xxxx.ssm.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut" />
aop:config>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="configLocation" value="classpath:mybatis.xml" />
<property name="mapperLocations" value="classpath:com/xxxx/ssm/mapper/*.xml" />
bean>
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xxxx.ssm.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
bean>
beans>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.xxxx.ssm.po"/>
typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
configuration>
在项⽬的 src/main/resources 下创建 db.properties ⽂件,内容如下(mysql 创建数据库ssm)
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
jdbc.username=root
jdbc.password=root
在项⽬的 src/main/resources 下创建 log4j.properties ⽂件,内容如下
log4j.rootLogger=DEBUG, Console
# Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
在项⽬的 src/main/java 下创建对应的包结构
com.xxxx.ssm.controller
com.xxxx.ssm.service
com.xxxx.ssm.mapper
com.xxxx.ssm.dao
com.xxxx.ssm.po
在 com.xxxx.ssm.po 包下创建 JavaBean ⽂件 User.java (数据库字段对应如下)

public class User {
private Integer userId;
private String userName;
private String userPwd;
private String userEmail;
private Date createDate;
private Date updateDate;
}
com.xxxx.ssm.dao 包下创建 UserDao.java ⽂件,提供对应的⽤⼾详情查询功能
public interface UserDao {
User queryUserByUserId(Integer userId);
}
com.xxxx.ssm.mapper 包下创建 UserMapper.xml ⽂件,提供select 查询标签配置
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.ssm.dao.UserDao">
<select id="queryUserByUserId" parameterType="int" resultType="com.xxxx.ssm.po.User">
select user_id as userId,user_name as userName,user_pwd as userPwd
from tb_user
where user_id = #{userId}
select>
mapper>
com.xxxx.ssm.service 包下创建UserService.java ⽂件,提供⽤⼾详情查询⽅法
@Service
public class UserService {
// 注入userDao
@Autowired
private UserDao userDao;
public User queryUserByUserId(Integer userId){
User user = userDao.queryUserByUserId(userId);
return user;
}
}
在 com.xxxx.ssm.controller 包下创建 HelloController.java ⽂件
@Controller
public class UserController extends BaseController {
// 注入userService
@Autowired
private UserService userService;
@RequestMapping("/hello")
public String hello (Model model){
// 调用UserService层的方法
User user = userService.queryUserByUserId(1);
// 将数据存到model对象中
model.addAttribute("user",user);
return "hello";
}
}
在src/main/webapp/WEB-INF 创建jsp ⽬录,并在该⽬下创建hello.jsp ,展⽰查询的⽤⼾信息
<body>
欢迎你,${user.userName}
body>
模型 - 视图 - 控制器(MVC)是⼀个以设计界⾯应⽤程序为基础的设计思想。
Restful ⻛格的 API 是⼀种软件架构⻛格,设计⻛格⽽不是标准,只是提供了⼀组设计原则和约束条件。它主要⽤于客⼾端和服务器交互类的软件。基于这个⻛格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
在Restful ⻛格中,⽤⼾请求的 url 使⽤同⼀个 url,⽤请求⽅式:get,post,delete,put…等⽅式对请求的处理⽅法进⾏区分,这样可以在前后台分离式的开发中使得前端开发⼈员不会对请求的资源地址产⽣混淆和⼤量的检查⽅法名的⿇烦,形成⼀个统⼀的接⼝。
GET(SELECT):从服务器查询,可以在服务器通过请求的参数区分查询的⽅式。
POST(CREATE):在服务器端新建⼀个资源,调⽤ insert 操作。
PUT(UPDATE):在服务器端更新资源,调⽤ update 操作。
PATCH(UPDATE):在服务器端更新资源(客⼾端提供改变的属性)。(⽬前 jdk7 未实现,tomcat7 不⽀持)。
DELETE(DELETE):从服务器端删除资源,调⽤ delete 语句。
SpringMVC 是通过 @RequestMapping 及 @PathVariable 注解提供的。
通过如@RequestMapping(value=“/blog /{id}”, method = RequestMethod.DELETE),即可处理 /blog/1 的 delete请求。
在 src/resources/java 对应的 com.xxxx.ssm.po ⽬录下新建 Account.java 实体类
public class Account {
private Integer id;
private String aname;
private String type;
private Double money;
private Integer userId;
private Date createTime;
private Date updateTime;
private String remark;
}
在 src/resources/java 对应的 com.xxxx.ssm.dao ⽬录下新建 AccountDao.java 接⼝类
public interface AccountDao {
public Account selectById(Integer id);
public int save(Account account);
public int update(Account account);
public int delete(Integer id);
}
在 src/resources/java 对应的 com.xxxx.ssm.mapper ⽬录下新建 AccountMapper.xml 映射⽂件
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.xxxx.ssm.dao.AccountDao" >
<resultMap id="BaseResultMap" type="com.xxxx.ssm.po.Account" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="aname" property="aname" jdbcType="VARCHAR" />
<result column="type" property="type" jdbcType="VARCHAR" />
<result column="money" property="money" jdbcType="DOUBLE" />
<result column="user_id" property="userId" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="DATE" />
<result column="update_time" property="updateTime" jdbcType="DATE" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
resultMap>
<sql id="Base_Column_List" >
id, aname, type, money, user_id, create_time, update_time, remark
sql>
<select id="selectById" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from tb_account
where id = #{id,jdbcType=INTEGER}
select>
<delete id="delete" parameterType="java.lang.Integer" >
delete from tb_account
where id = #{id,jdbcType=INTEGER}
delete>
<insert id="save" parameterType="com.xxxx.ssm.po.Account" >
insert into tb_account
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
if>
<if test="aname != null" >
aname,
if>
<if test="type != null" >
type,
if>
<if test="money != null" >
money,
if>
<if test="userId != null" >
user_id,
if>
<if test="createTime != null" >
create_time,
if>
<if test="updateTime != null" >
update_time,
if>
<if test="remark != null" >
remark,
if>
trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
if>
<if test="aname != null" >
#{aname,jdbcType=VARCHAR},
if>
<if test="type != null" >
#{type,jdbcType=VARCHAR},
if>
<if test="money != null" >
#{money,jdbcType=DOUBLE},
if>
<if test="userId != null" >
#{userId,jdbcType=INTEGER},
if>
<if test="createTime != null" >
#{createTime,jdbcType=DATE},
if>
<if test="updateTime != null" >
#{updateTime,jdbcType=DATE},
if>
<if test="remark != null" >
#{remark,jdbcType=VARCHAR},
if>
trim>
insert>
<update id="update" parameterType="com.xxxx.ssm.po.Account" >
update tb_account
<set >
<if test="aname != null" >
aname = #{aname,jdbcType=VARCHAR},
if>
<if test="type != null" >
type = #{type,jdbcType=VARCHAR},
if>
<if test="money != null" >
money = #{money,jdbcType=DOUBLE},
if>
<if test="userId != null" >
user_id = #{userId,jdbcType=INTEGER},
if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=DATE},
if>
<if test="updateTime != null" >
update_time = #{updateTime,jdbcType=DATE},
if>
<if test="remark != null" >
remark = #{remark,jdbcType=VARCHAR},
if>
set>
where id = #{id,jdbcType=INTEGER}
update>
mapper>
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
public Account selectById(Integer id){
return accountDao.selectById(id);
}
public int saveAccount(Account account){
return accountDao.save(account);
}
public int updateAccount(Account account){
return accountDao.update(account);
}
public int delAccount(Integer id){
return accountDao.delete(id);
}
}
/**
* RestFul URL 配置
* 1. 设置请求类型
* GET(查询) @GetMapping
* DELETE(删除) @DeleteMapping
* POST(添加) @PostMapping
* PUT(更新) @PutMapping
* 2. URL设置时,不体现动作行为 (没有动词)
* 例如:/account/1、/account/2、/account
* 3. 定义参数格式
* 1. 路径参数 ( @PathVariable )
* 2. json格式 ( @RequestBody )
* 3. 普通表单参数
* 4. 设置响应数据
* json格式 ( @ResponseBody )
*/
@Controller
public class AccountController extends BaseController {
@Autowired
private AccountService accountService;
/**
* 查询操作
* 传统的 URL 访问:
* http://localhost:8080/ssm/account/queryAccountById?id=1
* RestFul URL 访问:
* @GetMapping("/account/{id}")
* http://localhost:8080/ssm/account/1
* @PathVariable 将形参设置为参数路径,声明在形参前面
* @param id
* @return
*/
// @RequestMapping("/account/queryAccountById")
@GetMapping("/account/{id}")
@ResponseBody
public Account queryAccountById(@PathVariable Integer id) {
// 设置异常
return accountService.selectById(id);
}
/**
* 删除操作
* @param id
* @return
*/
@DeleteMapping("/account/{id}")
@ResponseBody
public Map<String,String> deleteAccountById(@PathVariable Integer id) {
// 调用service层的删除方法,返回受影响的行数
int row = accountService.delAccount(id);
// 判断受影响的行数是否大于0
Map<String ,String> map = new HashMap<>();
if (row > 0) {
// 删除成功
map.put("code","200");
map.put("msg","删除成功!");
} else {
// 删除失败
map.put("code","500");
map.put("msg","删除失败!");
}
return map;
}
/**
* 添加操作
* @param account
* @return
*/
@PostMapping("/account")
@ResponseBody
public Map<String,String> addAccount(@RequestBody Account account) {
Map<String ,String> map = new HashMap<>();
// 调用service层的添加方法,返回受影响的行数
int row = accountService.saveAccount(account);
// 判断受影响的行数是否大于0
if (row > 0) {
// 删除成功
map.put("code","200");
map.put("msg","添加成功!");
} else {
// 删除失败
map.put("code","500");
map.put("msg","添加失败!");
}
return map;
}
/**
* 更新操作
* @param account
* @return
*/
@PutMapping("/account")
@ResponseBody
public Map<String,String> updateAccount(@RequestBody Account account) {
Map<String ,String> map = new HashMap<>();
// 调用service层的添加方法,返回受影响的行数
int row = accountService.updateAccount(account);
// 判断受影响的行数是否大于0
if (row > 0) {
// 删除成功
map.put("code","200");
map.put("msg","更新成功!");
} else {
// 删除失败
map.put("code","500");
map.put("msg","更新失败!");
}
return map;
}
}
SpringMVC 对于异常处理这块提供了⽀持,通过 SpringMVC 提供的全局异常处理机制,能够将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单⼀,也实现了异常信息的统⼀处理和维护
全局异常实现⽅式 Spring MVC 处理异常有 3 种⽅式:
使⽤ Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver
实现 Spring 的异常处理接⼝ HandlerExceptionResolver ⾃定义⾃⼰的异常处理器
使⽤ @ExceptionHandler 注解实现异常处理
配置 SimpleMappingExceptionResolver 对象
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="error">property>
<property name="exceptionAttribute" value="ex">property>
bean>
可以在处理异常的⻚⾯获取异常信息
${ex}
参数异常
package com.xxxx.ssm.exception;
/**
* 自定义异常:参数异常
*/
public class ParamsException extends RuntimeException {
private Integer code = 300;
private String msg = "参数异常!";
public ParamsException() {
super("参数异常!");
}
public ParamsException(String msg) {
super(msg);
this.msg = msg;
}
public ParamsException(Integer code) {
super("参数异常!");
this.code = code;
}
public ParamsException(Integer code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
业务异常
package com.xxxx.ssm.exception;
/**
* 自定义异常:业务异常
*/
public class BusinessException extends RuntimeException {
private Integer code=400;
private String msg="业务异常!";
public BusinessException() {
super("业务异常!");
}
public BusinessException(String msg) {
super(msg);
this.msg = msg;
}
public BusinessException(Integer code) {
super("业务异常!");
this.code = code;
}
public BusinessException(Integer code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
<property name="exceptionMappings">
<props>
<prop key="com.xxxx.ssm.exception.BusinessException">errorprop>
<prop key="com.xxxx.ssm.exception.ParamsException">errorprop>
props>
property>
使⽤ SimpleMappingExceptionResolver 进⾏异常处理,具有集成简单、有良好的扩展性、对已有代码没有⼊侵性等优点,但该⽅法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适⽤。
/**
* 全局异常统⼀处理
*/
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("ex","默认错误信息");
return mv;
}
}
/**
* 全局异常统⼀处理
*/
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("ex","默认错误信息");
// 判断是否是⾃定义异常
if (ex instanceof ParamsException) {
mv.setViewName("params_error");
ParamsException e = (ParamsException) ex;
mv.addObject("ex", e.getMsg());
}
if (ex instanceof BusinessException) {
mv.setViewName("business_error");
BusinessException e = (BusinessException) ex;
mv.addObject("ex", e.getMsg());
}
return mv;
}
使⽤实现 HandlerExceptionResolver 接⼝的异常处理器进⾏异常处理,具有集成简单、有良好的扩展性、对已有代码没有⼊侵性等优点,同时,在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。
⻚⾯处理器继承 BaseController
public class BaseController {
@ExceptionHandler
public String exc(HttpServletRequest request,HttpServletResponse response,Exception ex){
request.setAttribute("ex", ex);
if(ex instanceof ParamsException){
return "error_param";
}
if(ex instanceof BusinessException){
return "error_business";
}
return "error";
}
}
使⽤ @ExceptionHandler 注解实现异常处理,具有集成简单、有扩展性好(只需要将要异常处理的 Controller 类继承于 BaseController 即可)、不需要附加Spring 配置等优点,但该⽅法对已有代码存在⼊侵性(需要修改已有代码,使相关类继承于 BaseController),在异常处理时不能获取除异常以外的数据。
在 web.xml 中通过(Websphere/Weblogic)或者(Tomcat)节点配置特定异常情况的显⽰⻚⾯。
<error-page>
<exception-type>java.lang.Throwableexception-type>
<location>/500.jsplocation>
error-page>
<error-page>
<error-code>404error-code>
<location>/404.jsplocation>
error-page>
<error-page>
<error-code>500error-code>
<location>/500.jsplocation>
error-page>