过滤器、监听器、拦截器

过滤器(Filter)

简介

Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等
过滤器是基于函数回调

用途

过滤敏感词汇
权限访问控制(用户是否已经登陆、有没有权限访问该页面)

生命周期

和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责
随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁

举例

struts2中的核心控制器,控制跳转视图等
web.xml

  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>*.action</url-pattern>
  </filter-mapping>

springboot中使用

@Component
@WebFilter(urlPatterns="/**", filterName = "requestAttrFilter")
public class RequestAttrFilter implements Filter {

    //排除不拦截的url
    private static final String[] EXCLUDE_PATH_PATTERNS = { "/user/get1", "/dept/get1"};

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        StringBuffer requestURL = req.getRequestURL();
        String uri = req.getRequestURI();
        //对一些url不拦截
        if (Arrays.asList(EXCLUDE_PATH_PATTERNS).contains(uri)) {
            chain.doFilter(request, response);
        }
        request.setAttribute("data", "request中放的数据");
        if (true) {
            //满足要求放行
            chain.doFilter(request, response);
        }

    }

    @Override
    public void destroy() {

    }
}
@GetMapping("/get5")
public ApiResult get5(@RequestAttribute String data, HttpServletRequest request) {
    log.info("@RequestAttribute注解获取:{}", data);
    log.info("HttpServletRequest中获取:{}", request.getAttribute("data"));
    return ApiResult.ok(data);
}

监听器(Listener)

简介

Listener实现了javax.servlet.ServletContextListener 接口的服务器端程序

用途

初始化的内容添加工作、设置一些基本的内容

生命周期

随web应用的启动而启动,只初始化一次,随web应用的停止而销毁

举例

spring容器加载配置信息
context-param:就是一些需要初始化的配置,放入context-param中,从而被监听器(这里特指org.springframework.web.context.ContextLoaderListener)监听,然后加载

web.xml

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

拦截器(Interceptor)

简介

在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法
基于JAVA的反射机制

用途

拦截器能把很多功能从Action中独立出来,分散到不同的拦截器里面
主要是用在插件上

生命周期

在action的生命周期中,拦截器可以多次被调用

举例

struts2的默认拦截器struts-default
struts.xml

<package name="demo01" namespace="/demo01" extends="struts-default">
<action name="userAction01" class="cn.itsource._01_action.UserAction01" method="execute"></action>
</package>

springboot中使用

public class RequestAttrInterceptor implements HandlerInterceptor {

    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     * 返回false,请求到此结束; 返回true,请求继续执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.setAttribute("data", "request中放的数据");
        return true;
    }

    /**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     * 此时可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        
    }

    /**
     * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行
     * 可以在此记录结束时间并输出消耗时间,进行资源清理工作
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    //注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(new RequestAttrInterceptor());
        //所有路径都被拦截
        registration.addPathPatterns("/**");
        //添加不拦截路径
        registration.excludePathPatterns("/**/*.html", "/**/*.js", "/**/*.css");
    }
}

springboot的注解用法

/**
 * 创建注解类
 * 在需要登录验证的Controller的方法上使用此注解
 */
@Target({ElementType.METHOD})// 可用在方法名上
@Retention(RetentionPolicy.RUNTIME)// 运行时有效
public @interface LoginRequired {
	
}
public class AuthorityInterceptor extends HandlerInterceptorAdapter{
	
	 @Override
	 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
	 	// 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // ①:START 方法注解级拦截器
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 判断接口是否需要登录
        LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);
        // 有 @LoginRequired 注解,需要认证
        if (methodAnnotation != null) {
            // 这写你拦截需要干的事儿,比如取缓存,SESSION,权限判断等
            System.out.println("====================================");
            return true;
        }
        return true;
	}
}
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
	 @Override
	 public void addInterceptors(InterceptorRegistry registry) {
        // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
        registry.addInterceptor(LoginInterceptor()).addPathPatterns("/**");
        registry.addInterceptor(AuthorityInterceptor()).addPathPatterns("/**");
	 }
	 
	 @Bean
	 public LoginInterceptor LoginInterceptor() {
		 return new LoginInterceptor();
	 }
	 
	 @Bean
	 public AuthorityInterceptor AuthorityInterceptor() {
		 return new AuthorityInterceptor();
	 }
}

也有一些教程使用的WebMvcConfigurationSupport,我使用后发现,classpath:/META/resources/,classpath:/resources/,classpath:/static/,classpath:/public/)不生效。具体可以原因,大家可以看下源码因为:WebMvcAutoConfiguration上有个条件注解:

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值