#SpringBoot中:
ServletRegistrationBean --注册--> Servlet
FilterRegistrationBean --注册--> Filter
ServletListenerRegistrationBean --注册--> Listener
1.Filter
过滤器是服务端的一个组件,是基于servlet实现从客户端访问服务端web资源的一种拦截机制,
对请求request和响应response都进行过滤,依赖于serverlet容器.
使用时,实现Filter接口,在web.xml里配置对应的class还有mapping-url,
springboot工程可以通FilterRegisteration配置后,设置要过滤的URL
#注意
两种方式过滤器都是有序的!
定义过滤器后会重写三个方法,分别是init(),doFilter(),和destory():
#init方法
是过滤器的初始化方法,当web容器创建这个bean的时候就会执行,
这个方法可以读取web.xml里面的参数
#doFilter方法
是执行过滤的请求的核心,当客户端请求访问web资源时,
这个时候我们可以拿到request里面的参数,对数据进行处理后,
通过filterChain方法将请求将请求放行,
也可以通过response对响应进行处理(比如压缩响应),然后会传递到下一个过滤器
#destory方法
是当web容器中的过滤器实例被销毁时,会被执行,释放资源
#summary
过滤器的生命周期为:
实例化(web.xml) --> 初始化(init) --> 过滤(doFilter) --> 销毁(destroy)
Filter.png
2.拦截器Interceptor
过滤器依赖serverlet容器,获取request和response处理,是基于函数回调,简单说就是“去取你想取的”;
拦截器是通过java反射机制,动态代理来拦截web请求,是“拒你想拒绝的”,他只拦截web请求,但不拦截静态资源
#拦截器的三个方法,preHandler(),postHandler(),afterCompletion()
#preHandler():
这个方法是在controller调用之前调用,通过返回true或者false决定是否进入Controller层
#postHandler():
在请求进入控制层之后调用,但是在处理请求抛出异常时不会调用
#afterCompletion():
在请求处理完成之后,也就是在DispatherServlet渲染了视图之后执行,
也就是说这个方法必定是执行,包含异常信息,它的主要作用就是清理资源
Interceptor.png
示例代码
package com.zy.netty.config;
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;
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(">>>>>>>>> preHandle");
// 如果请求URI是c1, 返回false进行拦截, 否则不拦截
return !"/c1".equals(request.getRequestURI());
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println(">>>>>>>>> postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println(">>>>>>>>> afterCompletion");
}
}
package com.zy.netty.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final MyInterceptor myInterceptor;
@Autowired
public WebConfig(MyInterceptor myInterceptor) {
this.myInterceptor = myInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor);
}
}
package com.zy.netty.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("c1")
public Object c1() {
System.out.println(".......c1..........");
return "c1";
}
@RequestMapping("c2")
public Object c2() {
System.out.println(".......c2..........");
return "c2";
}
}
#访问http://localhost:8080/c1, 被拦截, 打印信息为:
>>>>>>>>> preHandle
#访问http://localhost:8080/c2, 未被拦截, 打印信息为:
>>>>>>>>> preHandle
.......c2..........
>>>>>>>>> postHandle
>>>>>>>>> afterCompletion
summary
>> 拦截器是基于Java反射机制的, 过滤器是基于接口回调的
>> 过滤器依赖于servlet容器, 而拦截器不依赖servlet容器
>> 过滤器可以对所有请求起作用, 拦截器只对Action请求起作用
>> 拦截器可以访问Action上下文, 值栈里的对象, 过滤器不能
3.Listener
参考:
https://www.jianshu.com/p/a766267be3c6
java.util.EventListener
javax.servlet.http.HttpSessionListener
javax.servlet.ServletRequestListener
javax.servlet.ServletContextListener
package com.zy.netty.listener;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 自定义事件
*/
@Data
@AllArgsConstructor
public class OrderEvent {
private String msg;
}
package com.zy.netty.listener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* 事件处理程序: 监听器
*/
@Component
public class OrderEventListener {
@EventListener
public void handlerOrderEvent(OrderEvent event) {
System.out.println("监听到orderEvent, 开始处理msg: " + event.getMsg());
}
}
package com.zy.netty.listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
/**
* 事件触发
*/
@Service
public class OrderService {
@Autowired
private ApplicationContext context;
public void publishOrder(OrderEvent event) {
context.publishEvent(event);
}
}
package com.zy.netty;
import com.zy.netty.listener.OrderEvent;
import com.zy.netty.listener.OrderService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootNettyDemoApplicationTests {
@Autowired
private OrderService orderService;
@Test
public void fn01() {
orderService.publishOrder(new OrderEvent("order01"));
}
}
4.Filter
package com.zy.eureka.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
/**
* SpringMVC 中自定义 Filter, 并设置 Filter 的执行顺序 (优先级)
*/
@SuppressWarnings("all")
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean xssFilterRegistration = new FilterRegistrationBean();
xssFilterRegistration.setFilter(new XssFilter());
xssFilterRegistration.setName("xssFilter");
// order数字越小越先执行
xssFilterRegistration.setOrder(2);
xssFilterRegistration.addUrlPatterns("/*");
xssFilterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
return xssFilterRegistration;
}
@Bean
public FilterRegistrationBean csrfFilterRegistration() {
FilterRegistrationBean csrfFilterRegistration = new FilterRegistrationBean();
csrfFilterRegistration.setFilter(new CsrfFilter());
csrfFilterRegistration.setName("csrfFilter");
csrfFilterRegistration.setOrder(1);
csrfFilterRegistration.addUrlPatterns("/*");
csrfFilterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
return csrfFilterRegistration;
}
private static class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
if ((Objects.isNull(request1.getHeader("reqHeader01")))) {
return;
}
HttpServletResponse response1 = (HttpServletResponse) response;
response1.setHeader("xssHeader", "xss");
chain.doFilter(request, response);
}
}
private static class CsrfFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response1 = (HttpServletResponse) response;
response1.setHeader("csrfHeader", "csrf");
chain.doFilter(request, response);
}
}
}
当访问一个 controller 时, 其调用堆栈信息为:
https://blog.csdn.net/jjkang_/article/details/88548120
https://blog.csdn.net/WoddenFish/article/details/84836824 (filter)
网友评论