Java Web 监听器、过滤器、拦截器、Servlet 说明
一:Servlet
作用:是用Java编写的服务器端程序。
强烈建议大家看看 https://blog.csdn.net/qq_19782019/article/details/80292110 这个大兄弟对servlet总结的很好。
注意:web.xml 加载顺序为 context-param --》 listener --》 filter --》 servlet
public class CustomHttpServlet extends HttpServlet {
private CustomService customService = RegisterService.getService("CustomServiceImpl");
/**
* 覆盖 Get 方法
* @param request
* @param response
*/
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了doGet方法");
// 证明拦截器的存在
customService.doSomething("做点啥都行");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("<h3>"+ OnlineUser.getOnlineNumber()+"</h3>");
}
/**
* 覆盖 Post 方法
* @param request
* @param response
*/
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了doPost方法");
}
}
web.xml配置
<!-- 自定义 Http servlet-->
<servlet>
<servlet-name>customHttpServlet</servlet-name>
<servlet-class>com.engraver.servlet.CustomHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>customHttpServlet</servlet-name>
<url-pattern>/custom/http/servlet</url-pattern>
</servlet-mapping>
二:监听器
作用:监听器就是监听某个对象的的状态变化的组件。java web 监听器主要是指 ServletContextListener、HttpSessionListener、ServletRequestListener
实现方式:实现 ServletContextListener、HttpSessionListener、ServletRequestList 中的一个接口(职责单一原则)
ServletContextListener监听器的主要作用:
1、初始化的工作:初始化对象;初始化数据。比如加载数据库驱动,对连接池的初始化。
2、加载一些初始化的配置文件;比如spring的配置文件。
HttpSessionListener监听Httpsession域的创建与销毁的监听器。
ServletRequestListener监听ServletRequest域创建与销毁的监听器。ServletRequest的生命周期:每一次请求都会创建request,请求结束则销毁。
/**
* 自定义 ServletContextListener 监听器
*/
public class CustomListener implements ServletContextListener {
/**
* 初始化
* @param servletContextEvent
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("监听器初始化");
// 自定义注册拦截器
RegisterInterceptor.addInterceptor(CustomInterceptor.class);
// 自定义服务注册
RegisterService.addService(CustomServiceImpl.class);
}
/**
* 销毁
* @param servletContextEvent
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("监听器销毁");
}
}
/**
* 自定义 HttpSessionListener 监听器
*/
public class CustomSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
OnlineUser.add();
System.out.println("监听Session的创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
OnlineUser.remove();
System.out.println("监听Session的销毁");
}
}
web.xml 配置
<!-- 自定义监听器 -->
<listener>
<listener-class>com.engraver.listener.CustomListener</listener-class>
</listener>
<listener>
<listener-class>com.engraver.listener.CustomSessionListener</listener-class>
</listener>
三:过滤器
作用:filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行,并且可以对目 标资源访问前后进行逻辑处理。
实现方式:实现Filter接口
/**
* 自定义过滤器
*/
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("自定义过滤器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("自定义过滤器doFilter");
System.out.println("过滤器代码");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("自定义过滤器销毁");
}
}
web.xml 配置
<!-- 自定义过滤器 -->
<filter>
<filter-name>customFilter</filter-name>
<filter-class>com.engraver.filter.CustomFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>customFilter</filter-name>
<url-pattern>/custom/http/*</url-pattern>
</filter-mapping>
四:拦截器
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6、过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。过滤器包裹住servlet,servlet包裹住拦截器。
Java手写拦截器实现思路:
第一步:创建拦截器接口定义before 和 after 方法。
第二步:创建拦截器实现类,实现before 和 after 方法具体内容。
第三步:创建被代理类(拦截器依赖于动态代理),测试实例用为尽量还原实际开发中的情景,使用了service 和 serviceImpl 方法
第四步:创建动态代理类,传出被代理类和拦截器类对象。
第五步:编写拦截器注册类,利用反射机制
第六步:编写服务注册类,在服务注册时使用单实例通过动态代理模式建实例化的动态代理类注册到服务注册表的HashMap对象内。
第七步:在ServletContextListener监听器初始化时调用 拦截器注册 和 服务注册。
第八步:在 Servlet 类中获取相应的动态代理服务类。调用服务类方法会触动拦截器类的 before 和 after 方法
代码已托管于https://gitee.com/my_engraver/engraver_study.git 下的 study_web 工程。
/**
* @author Engraver
* @title: InterceptorInterface
* @description: 拦截器接口
*/
public interface InterceptorInterface {
/**
* 方法之前
*/
void before(Object[] args) throws Exception;
/**
* 方法之后
*/
void after(Object[] args) throws Exception;
}
/**
* @author Engraver
* @title: CustomInterceptor
* @description: 自定义拦截器
*/
public class CustomInterceptor implements InterceptorInterface {
/**
* 方法之前
*
* @param args
*/
@Override
public void before(Object[] args) throws Exception {
System.out.println("自定义拦截器before方法");
// throw new IOException("拦截器中出现了问题");
}
/**
* 方法之后
*
* @param args
*/
@Override
public void after(Object[] args) throws Exception {
System.out.println("自定义拦截器after方法");
}
}
/**
* @author Engraver
* @title: CustomService
* @description: 自定义服务
*/
public interface CustomService {
/**
* 想做点啥就做点啥
* @param params
* @return
*/
String doSomething(String params);
}
/**
* @author Engraver
* @title: CustomServiceImpl
* @description: 自定义服务实现类
*/
public class CustomServiceImpl implements CustomService {
@Override
public String doSomething(String params){
System.out.println("自定义服务 doSomething = " + params);
return "操作成功了哦";
}
}
/**
* @author Engraver
* @title: RegisterInterceptor
* @description: 自定义注册拦截器
*/
public class RegisterInterceptor {
/**
* 注册拦截表
*/
private static Map<String,InterceptorInterface> interceptorRegedit = new HashMap<>();
/**
* 增加拦截器到注册表
* @param tClass
*/
public static void addInterceptor(Class< ? extends InterceptorInterface> tClass){
try {
InterceptorInterface interceptorInterface = tClass.newInstance();
interceptorRegedit.put(tClass.getSimpleName(),interceptorInterface);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static InterceptorInterface getInterceptor(String key){
return interceptorRegedit.get(key);
}
}
/**
* @author Engraver
* @title: RegisterService
* @description: 服务注册表
*/
public class RegisterService {
/**
* 注册服务表
*/
private static Map<String, CustomService> serviceRegedit = new HashMap<>();
/**
* 增加服务到注册表
* @param tClass
*/
public static void addService(Class< ? extends CustomService> tClass){
// 获取拦截器
InterceptorInterface interceptorInterface = RegisterInterceptor.getInterceptor("CustomInterceptor");
// 动态代理
DynamicProxyHandler dynamicProxyHandler = new DynamicProxyHandler(interceptorInterface,tClass);
// 生成动态代理类
CustomService customService = dynamicProxyHandler.getProxy();
serviceRegedit.put(tClass.getSimpleName(),customService);
}
public static CustomService getService(String key){
return serviceRegedit.get(key);
}
}
/**
* @author Engraver
* @title: DynamicProxyHandler
* @description: 动态代理拦截器
*/
public class DynamicProxyHandler implements InvocationHandler {
/**
* 拦截器
*/
private InterceptorInterface interceptorInterface;
/**
* 被代理对象
*/
private Object target;
public DynamicProxyHandler(InterceptorInterface interceptorInterface,Class< ? extends CustomService> object) {
this.interceptorInterface = interceptorInterface;
try {
this.target = object.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用拦截器的方法
interceptorInterface.before(args);
// 调用被代理类的方法
Object result = method.invoke(target,args);
// 调用拦截器的方法
interceptorInterface.after(args);
return result;
}
/**
* 获取代理对象
* @param <T>
* @return
*/
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
}
public class CustomListener implements ServletContextListener {
/**
* 初始化
* @param servletContextEvent
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("监听器初始化");
// 自定义注册拦截器
RegisterInterceptor.addInterceptor(CustomInterceptor.class);
// 自定义服务注册
RegisterService.addService(CustomServiceImpl.class);
}
/**
* 销毁
* @param servletContextEvent
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("监听器销毁");
}
}
/**
* @author Engraver
* @title: CustomHttpServlet
* @description: 自定义Http servlet
*/
public class CustomHttpServlet extends HttpServlet {
private CustomService customService = RegisterService.getService("CustomServiceImpl");
/**
* 覆盖 Get 方法
* @param request
* @param response
*/
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了doGet方法");
// 证明拦截器的存在
customService.doSomething("做点啥都行");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("<h3>"+ OnlineUser.getOnlineNumber()+"</h3>");
}
/**
* 覆盖 Post 方法
* @param request
* @param response
*/
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了doPost方法");
}
}
web.xml 配置
<!-- 自定义 Http servlet-->
<servlet>
<servlet-name>customHttpServlet</servlet-name>
<servlet-class>com.engraver.servlet.CustomHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>customHttpServlet</servlet-name>
<url-pattern>/custom/http/servlet</url-pattern>
</servlet-mapping>
<!-- 自定义监听器 -->
<listener>
<listener-class>com.engraver.listener.CustomListener</listener-class>
</listener>