过滤器、拦截器、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());
    }
}

  

 

posted @ 2020-03-08 17:34  XUMT111  阅读(314)  评论(0)    收藏  举报