/**
* 环境
*Windows 7
*JDK 1.8
*SpringBoot 2.0.2
*Eclipse Photon
*/
所有的开发之中拦截器一定是一个必须要使用的功能,利用拦截器可以更加有效的实现数据的验证处理,而且最为幸运的是在 SpringBoot 之中所使用的拦截器与 Spring 中的拦截器完全一样。
项目所需JAR(pom文件)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.github.kischang</groupId>
<artifactId>fastdfs-client</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
第一部分 基础拦截器
1.创建SpringBoot启动类 (StartSpringBootMain.java)
package com.dxf.myspringboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 启动SpringBoot程序,而后自带子包扫描
public class StartSpringBootMain {
public static void main(String[] args) throws Exception {
SpringApplication.run(StartSpringBootMain.class, args);
}
}
2.创建Model(Member.java)
package com.dxf.myspringboot.model;
public class Member {
private Long mid;
private String name;
private int age;
private Double salary;
public Long getMid() {
return mid;
}
public void setMid(Long mid) {
this.mid = mid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Member [mid=" + mid + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
}
3.创建Member控制器(MemberController.java)
package com.dxf.myspringboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dxf.myspringboot.model.Member;
@Controller
public class MemberController {
@RequestMapping(value="/add_member_pre",method=RequestMethod.GET)
public String addMemberPre() {
return "add_member";
}
@RequestMapping(value="/add_member",method=RequestMethod.POST)
@ResponseBody
public Object addMember(Member member) {
return member;
}
}
4.编写HTML界面(add_member.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form th:action="@{/add_member}" method="post">
用户编号:<input type="text" name="mid" placeholder="请输入mid"/><br/>
用户姓名:<input type="text" name="name" placeholder="请输入用户名"/><br/>
<input type="submit" value="表单提交"/>
</form>
</body>
</html>
5.SpringBoot配置文件(application.yml)
server:
port: 80
此时一个正常的 MVC 的代码就实现完成了,在这里我们进行个小测试看下能否正常运行呢
首先在浏览器输入 localhost/add_member_pre
再输入各种参数
我们看下能否正常输出Restful
6.拦截器配置(MyInterceptor.java)
为了更好的说明问题,现在将拦截器定义在外包中;
package com.dxf.utils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
public class MyInterceptor implements HandlerInterceptor {
private Logger log = LoggerFactory.getLogger(MyInterceptor.class) ;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler ;
this.log.info("【*** MyInterceptor.preHandle() ***】" + handlerMethod.getBean().getClass().getSimpleName());
return true; // 如果返回false表示不继续请求,如果返回true表示继续请求
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler ;
this.log.info("【*** MyInterceptor.postHandle() ***】" + handlerMethod.getBean().getClass().getSimpleName());
this.log.info("【*** MyInterceptor.postHandle() ***】" + modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
this.log.info("【*** MyInterceptor.afterCompletion() ***】拦截处理完毕" );
}
}
7.那么此时如果要想使用拦截器则必须有一个拦截器的配置类。现在不在编写配置文件了,所有的配置直接利用一个类完成。(MyWebApplicationConfig.java)
package com.dxf.myspringboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.dxf.utils.MyInterceptor;
@Configuration
public class MyWebApplicationConfig extends WebMvcConfigurerAdapter{
@SuppressWarnings("deprecation")
@Override
public void addInterceptors(InterceptorRegistry registry) { // 进行拦截器的注册处理操作
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**") ; // 匹配路径
super.addInterceptors(registry);
}
}
现在只要找到了可以操作的控制器程序类,那么就可以依照在 Spring 中讲解的拦截器代码那样进行各种验证规则的编写以及相应的错误提示输出了。
附件(项目结构)
第二部分 AOP拦截器
在 Spring 里面还提供有一种 AOP 拦截器配置,不过大部分的 AOP 拦截器都是围绕着业务层进行拦截处理的。
1.业务层接口(IMemberService.java)
package com.dxf.myspringboot.service;
import com.dxf.myspringboot.model.Member;
public interface IMemberService {
public Member get(long mid) ;
}
2.业务层实现类(MemberServiceImpl.java)
package com.dxf.myspringboot.service.imp;
import org.springframework.stereotype.Service;
import com.dxf.myspringboot.model.Member;
import com.dxf.myspringboot.service.IMemberService;
@Service
public class MemberServiceImpl implements IMemberService {
@Override
public Member get(long mid) {
Member member = new Member();
member.setMid(mid);
member.setName("韩信");
member.setSalary(100000.00);
return member;
}
}
3.现在业务层的操作完成之后随意去修改控制层,让控制层进行业务层的调用
@Resource
private IMemberService memberService ;
@RequestMapping(value = "/member_get", method = RequestMethod.GET)
@ResponseBody
public Object get(long mid) {
return this.memberService.get(mid) ;
}
访问地址:http://localhost/member_get?mid=100
4.现在的业务层只是一个纯粹的调用而已,但是现在希望对调用的过程进行拦截处理,所以要想实现这样的处理,那么就需要
引入新的开发依赖包,修改 pom.xml 配置文件(这个我在之前已经加了):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
5.编写一个 AOP 拦截的控制程序类。
package com.dxf.myspringboot.config;
import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ServiceAspect { // 此时定义有一个业务层的拦截处理
private Logger log = LoggerFactory.getLogger(ServiceAspect.class);
@Around("execution(* com.dxf..service..*.*(..))")
public Object arroundInvoke(ProceedingJoinPoint point) throws Throwable {
this.log.info("【*** Service-Before ***】执行参数:"
+ Arrays.toString(point.getArgs()));
Object obj = point.proceed(point.getArgs()); // 进行具体业务调用
this.log.info("【*** Service-After ***】返回结果:" + obj);
return obj;
}
}
如果大家也是用Eclispe的话,切入成功会出现以下标记
6.测试
【启动StartSpringBootMain】---》【在浏览器输入http://localhost/member_get?mid=100】
看下后台输出