1,监听器
Java事件监听器是由事件类和监听接口组成,自定义一个事件前,必须提供一个事件的监听接口以及一个事件类。JAVA中监听接口是继承java.util.EventListener的类,事件类继承java.util.EventObject的类。
ApplicationListener是Spring框架提供的一个接口,它可以在Spring容器初始化完成或销毁之后,进行一系列的自定义操作。通过实现ApplicationListener接口,我们可以在程序启动或关闭时进行一些特定的操作,比如初始化一些资源、启动缓存、配置日志、关闭数据库连接等。通过监听Spring容器的启动和关闭消息,我们可以在应用启动时完成初始化操作,而在应用关闭时完成销毁操作。
通过spring的监听器,我们不仅可以实现自己相关的业务,还可以通过这个机制将我们自己的组件和spring进行整合,比如阿里的nacos就是通过ApplicationListener与spring整合的.
例:多租户多数据源初始化
@Slf4j @Configuration public class MyNacosConfigListening implements ApplicationListener<EnvironmentChangeEvent> { @Autowired private EnvironmentManager environmentManager; @Autowired private DataSource dataSource; @Override public void onApplicationEvent(EnvironmentChangeEvent event) { Set<String> keys = event.getKeys(); DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) this.dataSource; for (String key : keys) { if("dynamic.tenantId".equals(key)){ String val = (String) environmentManager.getProperty(key); String[] tenantDataSourceKeys = val.split(","); } } } }
nacos配置:
2,过滤器
Filter是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
例:将请求头的header信息如登录的账号信息,请求唯一标识traceId等存入ThreadLocal中以便取值
package com.yixin.saas.tb.configure; import com.yixin.auth.UserInfo; import com.yixin.auth.UserSessionContext; import org.springframework.context.annotation.Configuration; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration public class UserSessionFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; try { //登录账号信息 String account = httpRequest.getHeader("account"); String name = httpRequest.getHeader("name"); UserSessionContext.setUserSession(new UserInfo(account, name)); //请求唯一标识 String traceId = httpRequest.getHeader("traceId"); TraceIdSessionContext.setTraceIdSession(traceId); filterChain.doFilter(servletRequest, servletResponse); } finally { UserSessionContext.clearUserSession(); } } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } }
3,拦截器
Interceptor 在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。比如日志,安全等。一般拦截器方法都是通过动态代理的方式实现。可以通过它来进行权限验证,或者判断用户是否登陆,或者是像12306 判断当前时间是否是购票时间。
例:使用feign做服务间调用的时候,修改请求的头部信息
package com.yixin.auth; import feign.RequestInterceptor; import feign.RequestTemplate; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; @Component @Slf4j public class FeignInterceptorConfiguration implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { try { //登录账号信息 if (UserSessionContext.getUserSession() != null) { requestTemplate.header("account", UserSessionContext.getAccount()); requestTemplate.header("name", UserSessionContext.getCnName()); } //请求唯一标识 if (StringUtils.isNotBlank(TraceIdSessionContext.getTraceIdSession())) { requestTemplate.header("traceId", TraceIdSessionContext.getTraceIdSession()); } } catch (Exception e) { log.error("feign interceptor header error: {}", e.getMessage()); } } }