拦截器与过滤器的区别
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截器内容不同:Filter对所有访问进行增强(在Tomcat服务器进行配置),Interceptor仅针对SpringMVC的访问进行增强
一 使用maven新建Spring Boot项目
1. File --> New --> Project... --> Maven ,如下图所示
Project SDK下拉列表框中选择前面安装的 Java1.8,如果下拉列表框中不存在Java 1.8,可以单击New按钮,找到安装Java的位置,选择它。至于Maven中的archetype,不用勾选。然后单击“Next”
2. 给新工程起名springboot-interceptor-and-servletfilter,配置GAV
3.配置pom.xml
使用Maven,通过导入Spring Boot的 starter 模块,可以将许多程序依赖包自动导入工程中。使用Maven的parent POM,还可以更容易地管理依赖的版本和使用默认的配置,工程中的模块也可以很方便地继承它。使用如下代码清单所示的简单maven配置,基本上就能为一个使用Sping Boot开发框架的Web项目开发提供所需的相关依赖。
<?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>org.example</groupId>
<artifactId>springboot-interceptor-and-servletfilter</artifactId>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4. 创建Controller
在src/main/java下新建三级目录com/practice/demo,在该目录下创建 DemoApplication,以该类作为程序主入口
DemoApplication Controller代码如下
package com.practice.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class,args);
}
@RequestMapping("/")
public String hello() {
return "Hello, baby!";
}
}
运行该Spring boot应用。浏览器可访问,访问效果如下:
二 为Spring boot项目添加Servlet过滤器
Spring boot Servlet
过滤器是用于拦截应用程序的HTTP请求和响应的对象。通过使用过滤器,可以在两个实例上执行两个操作 -
- 在将请求发送到控制器之前
- 在向客户发送响应之前。
以下代码显示了带有@Component
注解的Servlet过滤器实现类的示例代码。
1. 在springboot项目 com.practice.demo目录下新建SimpleFilter类,该类实现 Filter 接口。
2. 在该实现类SimpleFilter的doFilter()方法中,添加 System.out.println()语句来打印运程主机和运程地址。
完整代码如下:
package com.practice.demo;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
@Component //只有加了该注解,才会生效。不加不生效(但不会报错)
public class SimpleFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 可sout快速打出System.out.println()
System.out.println("Remote Host:"+servletRequest.getRemoteHost());
System.out.println("Remote Address:"+servletRequest.getRemoteAddr());
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
3. 效果验证
打包,运行jar包
nohup java -jar springboot-interceptor-and-servletfilter-1.0.jar &
浏览器访问:localhost:8080/
查看服务日志,能看到打印了运程主机和运程地址
三 为Spring Boot项目添加拦截器
Spring Boot拦截器
在Spring Boot中使用拦截器,可在以下情况下执行操作 -
- 在将请求发送到控制器之前
- 在将响应发送给客户端之前
例如,使用拦截器在将请求发送到控制器之前添加请求标头,并在将响应发送到客户端之前添加响应标头。
要使用拦截器,需要创建支持它的@Component
类,它应该实现HandlerInterceptor
接口。
以下是在拦截器上工作时应该了解的三种方法 -
preHandle()
方法 - 用于在将请求发送到控制器之前执行操作。此方法应返回true
,以将响应返回给客户端。postHandle()
方法 - 用于在将响应发送到客户端之前执行操作。afterCompletion()
方法 - 用于在完成请求和响应后执行操作。
1.在springboot项目 com.practice.demo目录下新建子目录model,用来存放POJO类Product。
Product.java文件内容如下
package com.practice.demo.model;
public class Product {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.在springboot项目 com.practice.demo目录下新建ProductController类。
ProductController.java的代码如下:
package com.practice.demo;
import com.practice.demo.model.Product;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ProductController {
private static Map<String,Product> productRepo = new HashMap<>();
static {
Product apple = new Product();
apple.setId("1");
apple.setName("Apple");
productRepo.put(apple.getId(),apple);
Product beaf =new Product();
beaf.setId("2");
beaf.setName("Beaf");
productRepo.put(beaf.getId(),beaf);
}
@RequestMapping(value = "/products")
public ResponseEntity<Object> getProduct() {
return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
}
}
此时,该SpringBoot项目已有两个Controller,项目可正常启动,访问控制器。
3. 在springboot项目 com.practice.demo目录下新建interceptor子目录,用来存放拦截器和Spring MVC配置适配器。
a. 创建一个实现了HandlerInterceptor接口的拦截器类,可重写其中的方法,有三个可重写方法: preHaddle、postHandle、afterCompletion
b. 创建一个实现了 WebMvcConfigurer 接口的配置适配器类,并重写 addInterceptors 方法来注册拦截器。在重新的addInterceptors方法中,使用registry.addInterceptor()来添加拦截器,并通过addPathPatterns()来指定要拦截的路径模式,也可以使用excludePathPatterns()排除某些路径。
c.运行应用程序后,拦截器将根据配置的路径模式拦截相应的请求,并执行定义的操作。
ServiceInterceptor.java文件内容如下
package com.practice.demo.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 访问任意Controller的时候都会调用该实现类的三个方法
*/
@Component
public class ServiceInterceptor implements HandlerInterceptor {
// 默认不会重写实现访问
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("PreHaddler method is Calling");
return true; // 默认return false
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("PostHandle method is Calling");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Ruquest and Response is completed");
}
}
ServiceInterceptorConfigAdapter.java文件内容如下:
package com.practice.demo.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//定制 SpringMVC的一些功能都使用WebMvcConfiguer
@Component
public class ServiceInterceptorConfigAdapter implements WebMvcConfigurer {
//默认不会重写实现方法
@Autowired
ServiceInterceptor serviceInterceptor;
/**
* 服务启动的时候就会调用该方法
*
* @param registry 相当于拦截器的注册中心
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//往注册中心添加拦截器
registry.addInterceptor(serviceInterceptor).excludePathPatterns();
System.out.println("往注册中心添加拦截器");
}
}
4.效果验证
启动项目,发现启动的时候调用了 配置适配器的 addInterceptors方法,而访问 http://localhost:8080/products 和 http://localhost:8080/ 都会调用拦截器里的方法。