过滤器、拦截器、aop、泛型、枚举
Pattern.matches 过滤器,匹配url
EXCLUDE_URL_LIST.add(".*/deparement_new/*.*");
过滤器
@Configuration
public class FilterConfig {
//可以不配置
@Bean
public FilterRegistrationBean commonFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(commonFilter);
registration.addUrlPatterns("/jms/mail/getMailMessageDetailById");//必须是全路径
registration.setName("commonFilter");
registration.setOrder(1);
return registration;
}
@Component
@RequiredArgsConstructor
public class CommonFilter implements Filter {
private final XianTaoChannelInfoCache xianTaoChannelInfoCache;
private final XianTaoMsgBaseInfoCache xianTaoMsgBaseInfoCache;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
log.info("ThreadLocal移除removeChannelInfo避免内存泄漏");
xianTaoChannelInfoCache.removeChannelInfo();
xianTaoMsgBaseInfoCache.removeMsgBaseInfo();
}
@Override
public void destroy() {
}
@Service
public class XianTaoChannelInfoCache {
private ThreadLocal<List<MsgChannelInfo>> channelInfo = new ThreadLocal<>();
public List<MsgChannelInfo> getChannelInfos() {
return channelInfo.get();
}
public void setChannelInfos(List<MsgChannelInfo> list) {
this.channelInfo.set(list);
}
public void removeChannelInfo(){
this.channelInfo.remove();
}
}
增强版 TransmittableThreadLocal InheritableThreadLocal
@Bean
public FilterRegistrationBean senFilterProxy() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new WhaleFilter());
Map initParameters = Maps.newHashMap();
initParameters.put("config-file", "config-file.properties");
registration.setInitParameters(initParameters);
registration.addUrlPatterns("/*");
registration.setName("whaleFilter");
registration.setOrder(-1);
return registration;
}
使用参数
public class WhaleFilter implements Filter {
public void init(FilterConfig c) throws ServletException {
String path = c.getInitParameter("config-file");
if (path != null) {
InputStream ins = getClass().getClassLoader().getResourceAsStream(path);
if (ins == null)
ins = c.getServletContext().getResourceAsStream(path);
props.load(ins);
props.getProperty("upload.enable")

过滤器(Filter)和拦截器(Interceptor)的执行顺序是过滤器先于拦截器处理请求。 过滤器依赖于Servlet容器,可以对几乎所有请求进行过滤,而拦截器依赖于SpringMVC框架,主要对控制器请求进行拦截。 过滤器(Filter) 1,过滤器依赖于servlet容器,web.xml配置,是JavaEE标准,是在请求进入容器之后,还未进入Servlet之前进行预处理 2,过滤器是基于Java Servlet规范的一部分,用于在请求到达Servlet之前或响应离开Servlet之后对请求和响应进行处理。过滤器可以在服务器启动时初始化,并在每次用户访问目标资源时执行。过滤器的生命周期包括初始化、执行和销毁三个阶段,
其中初始化方法init在服务器启动时调用一次,销毁方法destroy在服务器关闭时调用一次。 拦截器(Interceptor) 1,拦截器是SpringMVC框架的一部分,基于Java的反射机制实现,属于面向切面编程(AOP)的一种应用。拦截器在控制器生命周期内可以多次调用,主要用于在服务方法调用前后执行特定的逻辑。拦截器的执行顺序是在过滤器之后,主要对控制器请求进行拦截,无法直接拦截静态资源请求 2,能获取request和response对象,对请求和响应进行处理,使用拦截器时,我们可以通过handler来获取当前请求控制器的方法名称,但是有一个弊端,我们拿不到控制器要接收的参数 过滤器:适用于需要处理所有请求的场景,如统一字符编码设置、XSS攻击防护等。 在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等 拦截器:适用于需要在业务逻辑前后执行特定操作的场景,如用户登录校验、权限检查等。 aop 面对的是处理过程中的方法或者阶段,以获得各部分的低耦合性的隔离效果,它是基于动态代理,它关注的是行为和过程 都能拿到请求信息 过滤器(Filter) :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息。 拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数。 切片 (Aspect) : 可以拿到方法的参数,但是却拿不到http请求和响应的对象
过滤器可以修改request,而拦截器不能
拦截器可以调用IOC容器中的各种依赖,而过滤器使用@Comonpent全局过滤时可以调用IOC依赖
拦截器有三个方法,相对于过滤器更加细致,有被拦截逻辑执行前、后等。
AOP针对具体的代码,能够实现更加复杂的业务逻辑。
过滤器:
统一设置编码,过滤敏感字符
Filter是依赖于Servlet的,需要有Servlet的依赖。
Filter可以拦截所有请求。包括静态资源[css,js...]。
同一个过滤器不可重复使用
1、2过滤器调用顺序 2init 1inti 1doFilter 2doFilter
1,只要在Filter实现类上增加 @Component 相当于一个拦截/*的filter
优点: 可以 @Autowired 注入容器中的其他实例
@Component
@Slf4j
public class MyFilter implements Filter {
2,Filter 实现类 + FilterRegistrationBean构造 + @Configuration:正常urlpattern的Filter,并且可以设置Order
@Bean
public FilterRegistrationBean indexEsgFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean(new MyFilter());
registration.addUrlPatterns("/xmh/*");
registration.setName("MyFilter");
registration.setOrder(1);
return registration;
}
@Slf4j
public class MyFilter implements Filter {
3,Filter 实现类 + @WebFilter + 启动了加上@ServletComponentScan 正常urlpattern的Filter
@Slf4j
@WebFilter(filterName = "MyFilter",urlPatterns = "/xmh/*")
public class MyFilter implements Filter {
4, 第2种方式+spring容器中的实例引用
@Configuration
public class FeignAutoConfiguration implements RequestInterceptor , ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Bean
public FilterRegistrationBean indexEsgFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean(new MyFilter(applicationContext));
applicationContext传入到MyFilter实例中,就可以获取容器中的实例
private ApplicationContext applicationContext;
public MyFilter(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
abilityManager = applicationContext.getBean(AbilityManager.class);
@Slf4j
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
log.info("接受到请求host:{}, port:{}, address:{}, URI:{}",
request.getRemoteHost(), request.getRemotePort(), request.getRemoteAddr(), ((HttpServletRequest) request).getRequestURI());
log.info(request.getParameter("xmh"));
chain.doFilter(request, response);
}
@Override
public int getOrder() {
return 0;
}
}
拦截器:
日志记录、权限校验,也可以使用@Service注入拦截器到容器 使用@Autowired引入
拦截器是依赖于SpringMVC的,需要有mvc的依赖。
拦截器只能拦截action请求。不包括静态资源[css,js...]。 基于java反射机制实现
同一个拦截器可重复使用
registry.addInterceptor(myInterceptor()).addPathPatterns("/**");///asd/**
registry.addInterceptor(myInterceptor()).addPathPatterns("/**");
1、2拦截器调用顺序 1pre 2pre 2post 1post 2after 1after
springboot拦截器
@Configuration
public class MyConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns("/**") 表示拦截所有的请求,
// excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
//.addPathPatterns("/**").excludePathPatterns("/login", "/register");
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");///asd/**
}
}
public class MyInterceptor implements HandlerInterceptor {
//在请求处理之前进行调用(Controller方法调用之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception {
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
preHandle
调用时间:Controller方法处理之前
执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序一个接一个执行
若返回false,则中断执行,注意:不会进入afterCompletion
postHandle
调用前提:preHandle返回true
调用时间:Controller方法处理完之后,DispatcherServlet进行视图的渲染之前,也就是说在这个方法中你可以对ModelAndView进行操作
执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序倒着执行。
备注:postHandle虽然post打头,但post、get方法都能处理
afterCompletion 调用前提:preHandle返回true 调用时间:DispatcherServlet进行视图的渲染之后 多用于清理资源
springboot过滤器
@Configuration
public class MyConfig2 {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
LogMdcFilter filter = new LogMdcFilter();
registrationBean.setFilter(filter);
//设置过滤器拦截请求
List<String> urls = new ArrayList<>();
urls.add("/*");
registrationBean.setUrlPatterns(urls);
return registrationBean;
}
public class LogMdcFilter implements Filter {
private static final String UNIQUE_ID = "traceId";
@Override
public void init(FilterConfig filterConfig) {
System.out.println("init**********filter************************************");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter**********filter************************************");
boolean bInsertMDC = insertMDC();
try {
chain.doFilter(request, response);
} finally {
if(bInsertMDC) {
MDC.remove(UNIQUE_ID);
}
}
}
@Override
public void destroy() {
}
private boolean insertMDC() {
UUID uuid = UUID.randomUUID();
String uniqueId = uuid.toString().replace("-", "");
MDC.put(UNIQUE_ID, uniqueId);
return true;
}
}
过滤器
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>cn.com.action.MyFileter</filter-class>
<!--<init-param>-->
<!--<param-name>logonStrings</param-name><!– 对登录页面不进行过滤 –>-->
<!--<param-value>/project/index.jsp;login.do</param-value>-->
<!--</init-param>-->
<init-param>
<param-name>includeStrings</param-name><!-- 只对指定过滤参数后缀进行过滤 -->
<param-value>.do;.jsp</param-value>
</init-param>
<!--<init-param>-->
<!--<param-name>redirectPath</param-name><!– 未通过跳转到登录界面 –>-->
<!--<param-value>/index.jsp</param-value>-->
<!--</init-param>-->
<!--<init-param>-->
<!--<param-name>disabletestfilter</param-name><!– Y:过滤无效 –>-->
<!--<param-value>N</param-value>-->
<!--</init-param>-->
</filter>
public class MyFileter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
Map map = request.getParameterMap();
String name = request.getParameter("name");
String method = request.getMethod();
String uri = request.getRequestURI();
System.out.println(map+","+name+","+method+","+uri);
filterChain.doFilter(servletRequest,servletResponse);
}
tomcat中也有servlet-api包,这样,发生了冲突
解决方法:添加provided,因为provided表明该包只在编译和测试的时候用,所以,当启动tomcat的时候,就不会冲突了,完整依赖如下:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
字符编码过滤器
设置了CharacterEncodingFilter,但是依然中文乱码,因为tomcat配有配置编码格式,server.xml
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
1,泛型在很大程度上提高了java的程序安全,有些强制转换在编译期无法检测
2,提高了代码的重用性
泛型的程序设计,意味着编写的代码可以被很多不同类型的对象所重用
public class ResultVo<T> {
private int code;
private String message;
private T data;
}
ResultVo<DomainC> res = new ResultVo<DomainC>();
res.setData(new DomainC());
********** 实例注入 *************************************
@Autowired
PlantSon plantSon;
plantSon.getT(); //cn.com.domain.testT.domain.Apple@24457439
PlantSon son = new PlantSon();
Apple apple = new Apple();
son.setT(apple);
@Service
public class PlantSon extends PlateT<Apple>{
}
public class PlateT<T extends Fruit>{// T 可以替换为 M
@Autowired
protected T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
********** 边界 *************************************
Plate<? super Fruit> plate = new Plate<>();
plate.setT(apple);
plate.setT(orange);
System.out.println(plate.getT());
//上界 因此编译器并不能了解这里到底需要哪种 Fruit 的子类型,因此他不会接受任何类型的 Fruit
// extends修饰的只能取,不能放 通过构造方法放入数据
Plate<? extends Fruit> plate2 = new Plate<>(orange);
System.out.println(plate2.getT());
//super可取可放 无论是Fruit还是其子类Orange 都是可以存到集合类型是Fruit或者更高的父类的集合中
List<? super Fruit> list = new ArrayList();
list.add(fruit);
list.add(orange);
System.out.println(list);
枚举好处:
1,限制了入参类型,提高编程安全
2,增加代码可读性,降低维护成本
public enum XmhEnum {
ITEM_1(1,"ONE"),ITEM_2(2,"TOW");
private int code;
private String name;
XmhEnum(int i, String one) {
this.code = i;
this.name = one;
}
public int getCode(){
return this.code;
}
public String getName(){
return this.name;
}
public static String getNameByCode(int code){
for(XmhEnum enums:XmhEnum.values()){
if(code == enums.getCode()){
return enums.getName();
}
}
return "";
}
public static void deals(XmhEnum enums){
System.out.println(enums.getName());
}
}

浙公网安备 33010602011771号