一.过滤器
1.什么是过滤器
过滤器(Filter)依赖于servlet容器,是实现了javax.servlet.Filter接口的程序,基于函数回调,主要可以过滤字符编码,做一些业务逻辑判断,比如token验证,用户是否登录等等。当在web.xml中配置好要拦截的客户端请求,就会对拦截的请求进行处理。它是随着web应用的启动而启动的,只初始化一次,当应用停止或重新部署才会销毁。
2.过滤器中的方法
void init(FilterConfig filterConfig) 用于完成过滤器的初始化。
void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) 实现过滤功能,该方法对每个请求增加额外处理,主要处理方法
在doFilter方法中
chain.doFilter(request, response);//需要放行时,需要调用FilterChain的doFilter方法。
void destroy() 用于过滤器销毁前,完成某些资源的回收。
3.过滤器案例
过滤器类需要实现Filter接口
public class HelloFilter implements Filter{
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//用到session,需要先强转http标准
HttpServletRequest req=(HttpServletRequest)request;
if(req.getSession().getAttribute("admin")==null){
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<script type='text/javascript'>alert('请登录后操作!');location='../index.jsp';</script>");
}else{
chain.doFilter(request, response);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
在web.xml中需要配置,哪些请求被过滤,以及指定哪个过滤器处理
<!-- 配置过滤器 -->
<filter><!-- 注册过滤器 -->
<filter-name>HelloFilter</filter-name>
<filter-class>filter.HelloFilter</filter-class>
</filter>
<filter-mapping><!-- 配置哪些请求需要过滤 -->
<filter-name>HelloFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.多个过滤器的执行顺序跟xml中定义的先后关系有关。
二.拦截器
1. 什么是拦截器
拦截器(Interceptor):依赖于web框架,实现了HandlerInterceptor接口。在springmvc中就是依赖于springmvc框架,基于java的反射机制,属于aop的一种应用。在你的service或者调用一个方法前,后或抛出异常时做相应的逻辑操作。拦截器可以使用依赖注入来执行一些业务操作,同时一个拦截器可以在一个controller生命周期中多次调用。
2.拦截器中的方法
preHandle方法:进入Handler方法之前执行,可用于身份验证,没有登陆返回false不往下执行,否则返回true.
postHandle方法:进入Handler方法之后,返回ModelAndView之前执行。该方法中又ModelAndView的形参。
afterCompletion方法:执行完Handler之后执行。比如统一日志处理等。
3.拦截器的案例
public class InterceptorUtil implements HandlerInterceptor{
//进入Handler方法之前执行
//可以用于身份认证、身份授权。如果认证没有通过表示用户没有登陆,需要此方法拦截不再往下执行,否则就放行
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("InterceptorUtil...........preHandle");
String user= (String) request.getSession().getAttribute("user");
if(user != null){
return true;
}
request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response);
//true表示放行,false表示不放行
return false;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("InterceptorUtil...........postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("InterceptorUtil...........afterCompletion");
}
}
在springmvc.xml或者structs.xml配置文件中:
<!-- 拦截器配置 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<!-- 登陆认证拦截器 -->
<mvc:interceptor>
<!-- /** 表示拦截所有url包括子url路径,/*只拦截根下的url -->
<mvc:mapping path="/**"/>
<bean class="com.cn.util.InterceptorUtil"></bean>
</mvc:interceptor>
<!-- 其他拦截器 -->
</mvc:interceptors>
三.过滤器与拦截器比较
1.两者的区别
-
过滤器是基于函数回调,拦截器是基于反射机制。
-
过滤器依赖于servlet容器,拦截器依赖于web容器
-
过滤器可以对几乎所有请求起作用,拦截器只对action请求起作用
-
过滤器不能访问action的上下文和值栈中的对象,拦截器可以
-
过滤器在servlet容器初始化时被调用一次,拦截器可以被多次调用
2.两者的使用场景
-
过滤器(Filter):当你有一堆东西时,你只希望选择符合你要求的一些东西,定义这些要求的工具就是过滤器。
-
拦截器(Interceptor):在一个流程正在进行时,你希望干预他的进展,甚至终止他的进行,可以用到拦截器
3.两者的执行顺序
四.监听器
1.什么是监听器
监听器用于监听web应用中的某些对象,信息的创建,销毁,增加,修改,删除等动作的发生,然后做出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。此技术常用在统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等。
2.监听器实例
监听在线人员
实现思路:在application启动时,放入List存放在线人员名单,在sessionsetAttribute时,向List中添加信 息放入app,session销毁时,向List中信息移除后再放入app
public class OnlineListener implements ServletContextListener,HttpSessionAttributeListener,HttpSessionListener{
private ServletContext application=null;
public void contextDestroyed(ServletContextEvent arg0) {
}
//在application启动时,放入List存放在线人员名单
public void contextInitialized(ServletContextEvent sce) {
List users=new ArrayList();
application=sce.getServletContext();
application.setAttribute("users", users);
}
//在sessionsetAttribute时,向List中添加信息放入app
public void attributeAdded(HttpSessionBindingEvent hsbe) {
List users=(List)application.getAttribute("users");
String username=(String)hsbe.getValue();
users.add(username);
application.setAttribute("users", users);
}
public void attributeRemoved(HttpSessionBindingEvent arg0) {
}
public void attributeReplaced(HttpSessionBindingEvent arg0) {
}
public void sessionCreated(HttpSessionEvent arg0) {
}
//session销毁时,将List中信息移除后再放入app
public void sessionDestroyed(HttpSessionEvent hse) {
List users=(List)application.getAttribute("users");
//取出当前销毁的session中的username
String username=(String)hse.getSession().getAttribute("username");
users.remove(username);
application.setAttribute("users", users);
}
}
注册监听器:
<listener>
<listener-class>listener.OnlineListener</listener-class>
</listener>
在web-xml中配置时,要注意配置文件的顺序:监听器--》过滤器--》servlet。
五.springboot中的监听器,过滤器和拦截器的使用
1.监听器的注册
@Configuration
public class ListenerConfig {
// 这里会直接注入
@Bean
public StartupListener startupListener() {
return new StartupListener();
}
2.拦截器的注册
@Configuration
public class MvcConfig implements WebMvcConfigurer {
/**
* 注册配置的拦截器
* @param registry 拦截器注册器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 这里的拦截器是new出来的,在Spring框架中可以交给IOC进行依赖注入,直接使用@Autowired注入
registry.addInterceptor(new UrlInterceptor());
}
}
//使用自动注入的方式注入拦截器,添加应用、或不应用该拦截器的URI(addPathPatterns/excludePathPatterns)
// addPathPatterns 用于添加拦截的规则,excludePathPatterns 用于排除拦截的规则
registry.addInterceptor(urlInterceptor).addPathPatterns(new UrlInterceptor()).excludePathPatterns("/login")
3.过滤器的注册
@Order(2)
@WebFilter(urlPatterns = {"/user/*"}, filterName = "loginFilter")
public class SessionFilter implements Filter {
}
上述的配置中,头部的有两个注解:
@Order注解: 用于标注优先级,数值越小优先级越大;
@WebFilter注解: 用于标注过滤器,urlPatterns指定过滤的URI(多个URI之间用逗号分隔),filterName指定名字;
注: 使用@WebFilter注解,必须在Springboot启动类上加@ServletComponentScan注解,否则该注解不生效,过滤器无效!
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new UrlInterceptor()());
registration.addUrlPatterns("/*");
registration.setName("CostTimeFilter");
registration.setOrder(1);
return registration;
}
}
springboot中的监听器,过滤器和拦截器的使用详细可参考博文:https://blog.csdn.net/jacksonary/article/details/84572701