参考:https://blog.csdn.net/wozaibohaibian/article/details/124778494
servlet就是一个组件,需要符合servlet规范,并且需要部署到servlet容器里面才能运行
注:容器:符合相应的规范,提供组件运行环境的程序。比如Tomcat就是比较有名的servlet容器。jetty jboss weblogic都是servlet容器。这些servlet把网络相关的问题已经全部处理好,我们写servlet只需要关注业务逻辑即可。
参考:https://zhuanlan.zhihu.com/p/340673453
过滤器
过滤器(Filter)属于Servlet的范畴,可以认为是Servlet的一种“加强版”,通过实现javax.servlet.Filter接口来实现功能。主要用于对用户请求进行预处理,是个典型的处理链。通常使用场景:==检查用户授权、记录日志信息、解码、过滤字符编码==等。
配置完过滤器及需要拦截的请求,当请求到来时,通过过滤器提供的方法可以对请求或响应(Request、Response)统一处理。比如,可判断用户是否登录,是否拥有请求的访问权限等。在Web应用启动时,过滤器仅会被初始化一次,便可处理后续请求,只有Web应用停止或重新部署时才能销毁。
使用Filter完整的流程是:Filter对用户请求进行“预处理”,接着将请求交给Servlet进处理并生成响应,最后Filter再对服务器响应进行“后处理”。
上述流程具体到类的处理就是:
创建Filter必须实现javax.servlet.Filter接口,该接口定义了3个方法:
其中,doFilter方法便是实现对用户请求进行预处理(ServletRequest request)和对服务器响应进行后处理(ServletResponse response)的方法。预处理和后处理的分界线为是否调用了chain.doFilter()。在执行该方法之前,是对用户请求进行预处理,在执行该方法之后,是对服务器响应进行后处理。
代码展示:
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter 初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter 预处理");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("Filter 后处理");
}
@Override
public void destroy() {
System.out.println("容器销毁");
}
}
关于Filter的使用在普通的Web项目中可在web.xml中配置:
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>com.secbro2.learn.filter.LogFilterfilter-class>
<async-supported>trueasync-supported>
<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>
如果是SpringBoot项目,首先使用@Component将LogFilter实例化,然后通过如下配置文件,进行具体的配置:
@Configuration
public class FilterConfig {
@Resource
private LogFilter logFilter;
@Bean
public FilterRegistrationBean<Filter> registerAuthFilter() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(logFilter);
registration.addUrlPatterns("/*");
registration.setName("authFilter");
// 值越小,Filter越靠前
registration.setOrder(1);
return registration;
}
}
定义一个Contoller,然后依次执行启动项目、访问Controller、关闭项目,打印的日志信息依次为:
Filter 初始化
---以上为启动项目时打印---
Filter 预处理
Controller中处理业务逻辑
Filter 后处理
---以上为访问Controller时打印---
容器销毁
---以上为关闭服务时打印---
拦截器
拦截器,在AOP(Aspect-Oriented Programming)中用于某个方法或字段被访问之前进行拦截,然后在其之前或之后加入某些操作。拦截器作为动态拦截Action调用的对象,它提供了一种机制使开发者可以在Action执行前后定义可执行的代码,也可以在Action执行前阻止其执行。拦截器将Action共用的行为独立出来,在Action执行前后执行。常见的应用场景比如权限管理、日志服务等。
如何实现
在Spring MVC当中要使用拦截器需要实现org.springframework.web.servlet.HandlerInterceptor接口,该接口定义了如下3个方法:
示例:
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("Interceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
System.out.println("Interceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("Interceptor afterCompletion");
}
}
对应LoginInterceptor需添加到Spring MVC当中:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
}
}
这里拦截所有的请求,执行对应的Controller之后,会看到打印如下信息:
当一个请求过来之后,会先后执行preHandle方法、Controller中的业务、postHandle方法和afterCompletion方法。
Interceptor preHandle
Controller中处理业务逻辑
Interceptor postHandle
Interceptor afterCompletion
过滤器 | 拦截器 | |
---|---|---|
原理不同 | 基于回调函数 | Java的反射机制实现 |
作用范围不同 | 实现javax.servlet.Filter接口,过滤器在只在Servlet前后起作用 | 定义在org.springframework.web.servlet包下,由Spring容器管理【又有更加丰富的生缪那个周期处理方法,细粒度,且能够使用Spring中的Bean资源,方便业务访问】,拦截器能够深入到方法前后、异常抛出前后,对Action请求其作用,可以访问Action上下文、值栈里的对象等,具有更大的弹性。因此,在Spring框架的过程中,要优先使用拦截器。 |
触发时机不同 | 对请求在进入后Servlet之前或之后进行处理 | 对请求在handler【Controller】前后进行处理。 |
使用资源不同 | 过滤器不能 | 拦截器可以使用Spring里的任何资源、对象,例如Service对象、数据源、事务管理等,通过IOC注入到拦截器即可 |
使用范围与规范不同 | 过滤器是Servlet规范中定义的,只能用于Web程序中,依赖于Servlet容器 | 拦截器是Spring的组件,可用于Web程序、Application、Swing等程序,不依赖Servlet容器 |
1、使用范围与规范不同:Filter是Servlet规范中定义的,只能用于Web程序中,依赖于Servlet容器。拦截器是Spring的组件,可用于Web程序、Application、Swing等程序,不依赖Servlet容器。
2、使用资源不同:拦截器可以使用Spring里的任何资源、对象,例如Service对象、数据源、事务管理等,通过IOC注入到拦截器即可;而Filter则不能。
3、作用范围不同:Filter在只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后,对Action请求其作用,可以访问Action上下文、值栈里的对象等,具有更大的弹性。因此,在Spring框架的过程中,要优先使用拦截器。而滤器则可以对几乎所有的请求起作用。
4、实现机制不同:拦截器是基于java的反射机制的,而过滤器是基于函数回调。