文章目录
过滤器(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)