-
2017-09-05 15:24:00
一、web.xml配置节点简介
(1) context-param
- 格式定义
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mybatis.xml</param-value> </context-param>
- 作用:该元素用来声明应用范围(整个WEB项目)内的上下文初始化参数。
param-name 设定上下文的参数名称。必须是唯一名称
param-value 设定的参数名称的值,这里的例子是指定spring配置文件的位置
(2) listener
- 格式定义
//listen-class 指定监听类,该类继承ServletContextListener 包含初始化方法contextInitialized(ServletContextEvent event) 和销毁方法contextDestoryed(ServletContextEvent event) <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- 作用:该元素用来注册一个监听器类。可以收到事件什么时候发生以及用什么作为响应的通知。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。常与context-param联合使用。
(3) filter
- 格式定义
<filter> <filter-name>CharacterEncodingFilter</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> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 作用:用于指定WEB容器的过滤器, filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应;在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;根据程序需要修改请求和响应;在servlet被调用之后截获servlet的执行。
(4)servlet
- 格式定义//配置Spring MVC,指定处理请求的Servlet,有两种方式: //1. 默认查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml //2. 可以通过配置修改MVC配置文件的位置,需要在配置DispatcherServlet时指定MVC配置文件的位置。 //这里使用的是第二种方式 <!-- Springmvc的核心控制器 --> <servlet> <servlet-name>dispatchServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatchServlet</servlet-name> <url-pattern>*.shtml</url-pattern> </servlet-mapping>
- 作用: 创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
创建可嵌入到现有的html页面中的一部分html页面(html片段);
读取客户端发来的隐藏数据;
读取客户端发来的显示数据;
与其他服务器资源(包括数据库和java的应用程序)进行通信;
二、 web.xml加载过程(步骤):
- 启动web项目,容器(如Tomcat、Apache)会去读取它的配置文件web.xml 中的两个节点,context-param和listener。
- 紧接着,容器将创建一个ServletContext(又称为:Servlet上下文),应用范围内即整个WEB项目都能使用这个Servlet上下文。
- 容器将< context-param >转化为键值对,并交给ServletContext。
- 容器创建< listener >中的类实例,即创建监听。(备注:listener定义的类可以是自定义的类但必须需要继承ServletContextListener)。
- 在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得:ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter(“context-param的键”); 在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法。用于关闭应用前释放资源,比如说数据库连接的关闭。
- 得到这个context-param的值之后,你就可以做一些操作了。注意,这个时候你的WEB项目还没有完全启动完成。这个动作会比所有的Servlet都要早。
换句话说,这个时候,你对 < context-param > 中的键值做的操作,将在你的WEB项目完全启动之前被执行。 举例.你可能想在项目启动之前就打开数据库。那么这里就可以在< context-param >中设置数据库的连接方式,在监听类中初始化数据库的连接。
补充知识:ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。例如,一个购物网站,用户要访问商品的详细信息,如果放在session域,每个用户都要访问一遍数据库,这样效率太低;而放在ServletContext中,服务器一启动,就访问数据库将商品信息放入数据库,这样所有用户只需要通过上下文就能访问到商品的信息。
三、web.xml节点加载顺序:
- web.xml节点的加载顺序与它们在web.xml中位置的先后无关,即不会因为< filter >写在< context-param >前面就先加载< filter >。
- 上文也提到到了,< context-param >用于对ServletContext提供键值对,即应用程序的上下文信息。而listener、servlet等节点在初始化的过程中会使用到这些上下文信息,所以最后我们得出web.xml节点的加载顺序应该为:context-param->listener->filter->servlet。
- 对于某类配置节点而言,位置的先后是有要求的。以servlet举例,与servlet相关的配置节点是servlet-mapping,对于拥有相同配置节servlet-name的servlet和servlet-mapping来说,servlet-mapping必须在servlet后定义,否则当解析到servlet-mapping时,它的servlet-name还没有定义。web 容器启动时初始化每个 servlet时,是按照 servlet配置节出现的顺序来初始化的。
- 最终结论: web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring] ,而同类型节点之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。
更多相关内容 -
详解Java Web项目启动执行顺序
2020-08-27 08:44:13主要介绍了详解Java Web项目启动执行顺序,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
web项目加载顺序
2018-11-19 00:01:31web项目执行顺序 现在主流的web开发框架一般都是基于Spring开发的,Spring生态圈量级非常之大,功能非常强大。今天讲述一下普通的web项目加载顺序。 虽然项目大部分都在使用SpringBoot、SpringCloud等微服务的架构来...@WEB
web项目执行顺序
现在主流的web开发框架一般都是基于Spring开发的,Spring生态圈量级非常之大,功能非常强大。今天讲述一下普通的web项目加载顺序。 虽然项目大部分都在使用SpringBoot、SpringCloud等微服务的架构来搭建项目,基本不会在进行这些配置了,但是如果项目追究Spring源码,这些基础知识还是需要了解的。
-
web.xml
web项目运行时首先会加载web.xml配置文件,一般该配置文件在 /WebRoot(web)/WEB-INF/web.xml ,web.xml中的内容加载不依赖于内容书写顺序,而是以 context-param 、 listener、 filter、servlet的顺序进行加载。web.xml中有以下几项内容:
(1)context-param
以下为配置spring配置文件目录的配置。该配置是针对整个web项目上下文的。<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
(2)listener
该配置用于向web容器中注册一个事件监听器,监听事件发生事件,如何响应等信息。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。常与context-param联合使用。<listener> // 该类继承ServletContextListener 包含初始化方法contextInitialized(ServletContextEvent event) 和销毁方法contextDestoryed(ServletContextEvent event) <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
(3)filter
filter 在web项目中起到过滤请求的作用,可配置在web.xml中,也可在项目中使用代码 继承Filter类来进行处理一些逻辑。Filter类中有 init(), doFilter(),destory() 方法。可获取到请求ServletRequest 和ServletResponse,然后决定继续处理哪些请求,阻挡哪些请求等。一般用作 防CRSF攻击、防SQL注入、权限过滤等 。
web.xml中filter 需要和 filter-mapping 一起使用,如下为字符过滤器。<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> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
public interface Filter { default void init(FilterConfig filterConfig) throws ServletException {} void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; default void destroy() {} }
(4)servlet
SpringMVC 中围绕 DispatcherServlet 来设计请求映射、视图处理、视图解析。DispatcherServlet 用于处理请求分发。具体内容见后续SpringMVC执行顺序。<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:SpringMVC.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
(5)欢迎页
web项目默认启动加载的页面。<welcome-file-list> <welcome-file>.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list>
SpringMVC执行顺序
- 时序图
2.组件
DispatcherServlet
前端控制器DispatcherServlet是SpringMVC整个流程控制中心,由它来调度其它组件相互配合,完成匹配请求URL,解析数据,响应数据,视图解析以及视图渲染等任务。
HandlerMapping
处理器映射器HandlerMapping负责根据用户请求URL找到匹配的Handler处理器。
HandlerAdapter
处理器适配器HandlerAdapter对处理器进行执行
ModelAndView
ModelAndView是Spring封装的model和view组合对象。可用于处理数据和视图。
ViewResolver
视图解析器ViewResolver负责处理结果生成视图,先根据逻辑视图名称找到物理视图地址,再生成视图对象,最后对视图进行渲染,将处理结果通过页面展现给用户。
Controller
业务逻辑处理器,接受请求参数,进行业务处理,返回响应的数据和视图。
3.applicationContext.xml和dispatcher-servlet.xml
applicationContext.xml 是Spring的全局配置文件,用来控制Spring特性,管理Bean的容器。
dispatcher-servlet.xml是SpringMVC中用作控制器,拦截器、转发view等作用。注意
在两个配置文件中最好不要声明相同的bean。 applicationContext.xml是随ContextLoaderListener而加载的,ContextLoaderListener 配置于 中的。dispatcher-servlet.xml是随DispatcherServlet而加载的,而DispatcherServlet配置于 中,在web.xml中加载顺序为 context-param 、listener 、 filter 、servlet 。所以先加载applicationContext.xml 再加载dispatcher-servlet.xml
-
-
Java Web项目启动时。web.xml执行顺序
2018-05-07 10:47:03转载出处:https://blog.csdn.net/qq_20805103/article/details/77851996 一、web.xml配置节点简介 (1) context-param 格式定义 <context-param> <param-name>context...转载出处:https://blog.csdn.net/qq_20805103/article/details/77851996
一、web.xml配置节点简介
(1) context-param
- 格式定义
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mybatis.xml</param-value> </context-param>
- 1
- 2
- 3
- 4
- 作用:该元素用来声明应用范围(整个WEB项目)内的上下文初始化参数。
param-name 设定上下文的参数名称。必须是唯一名称
param-value 设定的参数名称的值,这里的例子是指定spring配置文件的位置
(2) listener
- 格式定义
//listen-class 指定监听类,该类继承ServletContextListener 包含初始化方法contextInitialized(ServletContextEvent event) 和销毁方法contextDestoryed(ServletContextEvent event) <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- 1
- 2
- 3
- 4
- 作用:该元素用来注册一个监听器类。可以收到事件什么时候发生以及用什么作为响应的通知。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。常与context-param联合使用。
(3) filter
- 格式定义
<filter> <filter-name>CharacterEncodingFilter</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> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 作用:用于指定WEB容器的过滤器, filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应;在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;根据程序需要修改请求和响应;在servlet被调用之后截获servlet的执行。
(4)servlet
- 格式定义//配置Spring MVC,指定处理请求的Servlet,有两种方式: //1. 默认查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml //2. 可以通过配置修改MVC配置文件的位置,需要在配置DispatcherServlet时指定MVC配置文件的位置。 //这里使用的是第二种方式 <!-- Springmvc的核心控制器 --> <servlet> <servlet-name>dispatchServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatchServlet</servlet-name> <url-pattern>*.shtml</url-pattern> </servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 作用: 创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
创建可嵌入到现有的html页面中的一部分html页面(html片段);
读取客户端发来的隐藏数据;
读取客户端发来的显示数据;
与其他服务器资源(包括数据库和java的应用程序)进行通信;
二、 web.xml加载过程(步骤):
- 启动web项目,容器(如Tomcat、Apache)会去读取它的配置文件web.xml 中的两个节点,context-param和listener。
- 紧接着,容器将创建一个ServletContext(又称为:Servlet上下文),应用范围内即整个WEB项目都能使用这个Servlet上下文。
- 容器将< context-param >转化为键值对,并交给ServletContext。
- 容器创建< listener >中的类实例,即创建监听。(备注:listener定义的类可以是自定义的类但必须需要继承ServletContextListener)。
- 在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得:ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter(“context-param的键”); 在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法。用于关闭应用前释放资源,比如说数据库连接的关闭。
- 得到这个context-param的值之后,你就可以做一些操作了。注意,这个时候你的WEB项目还没有完全启动完成。这个动作会比所有的Servlet都要早。
换句话说,这个时候,你对 < context-param > 中的键值做的操作,将在你的WEB项目完全启动之前被执行。 举例.你可能想在项目启动之前就打开数据库。那么这里就可以在< context-param >中设置数据库的连接方式,在监听类中初始化数据库的连接。
补充知识:ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。例如,一个购物网站,用户要访问商品的详细信息,如果放在session域,每个用户都要访问一遍数据库,这样效率太低;而放在ServletContext中,服务器一启动,就访问数据库将商品信息放入数据库,这样所有用户只需要通过上下文就能访问到商品的信息。
三、web.xml节点加载顺序:
- web.xml节点的加载顺序与它们在web.xml中位置的先后无关,即不会因为< filter >写在< context-param >前面就先加载< filter >。
- 上文也提到到了,< context-param >用于对ServletContext提供键值对,即应用程序的上下文信息。而listener、servlet等节点在初始化的过程中会使用到这些上下文信息,所以最后我们得出web.xml节点的加载顺序应该为:context-param->listener->filter->servlet。
- 对于某类配置节点而言,位置的先后是有要求的。以servlet举例,与servlet相关的配置节点是servlet-mapping,对于拥有相同配置节servlet-name的servlet和servlet-mapping来说,servlet-mapping必须在servlet后定义,否则当解析到servlet-mapping时,它的servlet-name还没有定义。web 容器启动时初始化每个 servlet时,是按照 servlet配置节出现的顺序来初始化的。
- 最终结论: web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring] ,而同类型节点之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。
-
Java web项目自定义多个拦截器的执行顺序,以及拦截器的作用
2019-10-12 16:38:121. 为什么项目Controller的接口方法没有进入拦截器的preHandle? 2. 拦截器定义 3.如果preHandle返回为false,接下来会执行什么? 4. 多拦截器处理顺序? 5. 理论知识 5.1 prehandle 5.2 拦截器的基本概念? ...目录
1. 为什么项目Controller的接口方法没有进入拦截器的preHandle?
3.如果preHandle返回为false,接下来会执行什么?
前言:
最近总是整合和联系搭建项目,所以根据不同的需求有着不同的拦截器的写法,以及有的需求会有多个拦截器。
而拦截器用于 日志记录、用户登录状态拦截、安全拦截等等。
我的感情 我的人性 穿越世纪
你的记忆 你的秘密 依然清晰
我的回忆 我的思绪 不停累积
有你在一起 你是专属唯一
——《Wonderland》JJ
1. 为什么项目Controller的接口方法没有进入拦截器的preHandle?
原因是因为拦截器的配置还要进行注入。
拦截器也是需要代码中加入进去的。类似于这样。
@Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { @Autowired private RequestInterceptor requestInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //本项目把所有的路径都加入到拦截的请求中,根据需求可以具体来添加内容 registry.addInterceptor(requestInterceptor).addPathPatterns("/**"); super.addInterceptors(registry); } /** * 继承前端代码 * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); super.addResourceHandlers(registry); } }
2. 拦截器定义
package com.switcher.common.intercepter; import com.switcher.common.constant.ErrorConstants; import com.switcher.common.constant.SystemConstants; import com.switcher.data.Result; import com.switcher.utils.FastJsonUtils; import com.switcher.utils.ThreadLocalUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @Description : RequestInterceptor * 拦截处理类 * <p> * preHandle按拦截器定义顺序调用 * postHandler按拦截器定义逆序调用 * afterCompletion按拦截器定义逆序调用 * postHandler在拦截器链内所有拦截器返成功调用 * afterCompletion只有preHandle返回true才调用 * </p> * <p> * 支持异步线程方法中可能取不到值 * @Date : 2019/10/12 * @Author : pmdream */ @Component @Slf4j public class RequestInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 将请求初始参数存入threadLocal ThreadLocalUtil.setIsCacheFlag(false); //是否需要cache ThreadLocalUtil.setNeedCacheFlag(false); ThreadLocalUtil.setResponse(response); ThreadLocalUtil.setStartTime(System.currentTimeMillis()); //把请求中的globalRequestId 存入 String globalRequestId = request.getHeader(SystemConstants.REQUEST_ID); ThreadLocalUtil.setRequestId(globalRequestId); String userId = request.getHeader(SystemConstants.USER_ID); ThreadLocalUtil.setUserId(userId); String token = request.getHeader(SystemConstants.REQUEST_TOKEN_KEY); if (!SystemConstants.REQUEST_TOKEN_VALUE.equals(token)) { log.info("token验证异常! GlobalRequestId = {}", globalRequestId); PrintWriter writer = null; response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); try { writer = response.getWriter(); Result result = new Result(ErrorConstants.TOKEN_ERROR_MSG, ErrorConstants.TOKEN_ERROR_CODE, null, null); writer.print(FastJsonUtils.toJsonString(result)); return false; } catch (IOException e) { log.error("response返回响应信息异常!", e); } finally { if (writer != null) { writer.close(); } } } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { long totalTime = ThreadLocalUtil.getTotalTime(); log.info("===time===请求处理结束,总耗费时间:{}ms, 请求GlobalRequestId = {}", totalTime, ThreadLocalUtil.getRequestId()); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { ThreadLocalUtil.remove(); } }
3.如果preHandle返回为false,接下来会执行什么?
通过代码调试,发现如果返回false的话,是不会在进入postHandle 和afterCompletion
相当于预处理就已经出错了。
正常流程,pre - post -after
但是如果返回false 的话,那么就会直接在pre里面处理掉了。
当它返回为false 时,表示请求结束,后续的Interceptor 和Controller都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
那么如果是fasle,进入底层断点一下,再看一下底层的执行逻辑。
4. 多拦截器处理顺序?
一般来说,可以写两个拦截器或者更多拦截器,对于请求的URI不同,
然后进行不同的拦截器。
当然,如果有多个拦截器对一个请求路径呢?执行的顺序会是怎么样?
https://blog.csdn.net/syslbjjly/article/details/90675223
所以,正常放行情况
那么如果是异常情况呢?
拦截器都是链式的执行的,如果第一个pre就返回false,是不会进入第二个拦截器的。
-----如果第一个为true,第二个为false(只要有一个pre为false 也就是拦截器不放行,那么post就不会执行)
但是正常执行的拦截器,也就是放行的拦截器,是一定要执行afterCompletion()的。
已经自己校验过,图的话取得是上面链接博主的。
5. 理论知识
5.1 prehandle
SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法
5.2 拦截器的基本概念?
拦截器不依赖与Servlet容器,依赖于Spring等web框架。
拦截器是一种AOP的应用,底层是用的是Java反射机制来实现的。
于过滤器的很大区别是拦截器可以注入Spring的bean,这个通过上面的代码就可以看出来了。
拦截器在springboot的配置中就是可以用@Bean 注解 或者@Autowired 来进入。
拦截器与过滤器最大的区别可能是拦截器注入到Spring的 bean,能够获取到各种需要的Service来处理业务逻辑,
而过滤器不行。
拦截器可以继承HandlerInterceptorAdapter 或者HandlerInterceptor来实现。
另外,MVC的项目中的配置:
在spring-mvc的xml文件中,大体是这样的:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <import resource="classpath:view/view.xml"/> <import resource="classpath:security/security-mvc.xml"/> <mvc:annotation-driven/> <mvc:interceptors> <bean class="xxx.web.common.ApiLogInterceptor"/> </mvc:interceptors> <mvc:interceptors> <bean class="xxx.web.common.CORSInterceptor"/> </mvc:interceptors> <mvc:interceptors> <bean class="xxx.web.common.LoginInterceptor"/> </mvc:interceptors> <mvc:interceptors> <bean class="xxx.web.common.RequestLimitsInterceptor"/> </mvc:interceptors> <!-- 加载Controller --> <context:component-scan base-package="xxx" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> </beans>
所以,springboot还是简化了不少的东西。
拦截器的执行顺序:如果MVC的话语web.xml 里面配置的顺序有关,链式执行。
如果是springboot的话,那么就是在webMvc的配置文件中,注册的先后顺序。
PS:这里可能会被问到@Autowired到底是什么,相当于什么样的过程。
也可能面试官会引出AOP的相关概念,之后再补充。
5.3 什么是servlet容器?
https://blog.csdn.net/yw_1207/article/details/78706701
5.4 什么是过滤器?
Filter,依赖于Servlet容器,配置到web.xml文件中。也可以配置多个,执行的顺序是按照配置顺序的从上到下。
常用来配置一些请求编码和过滤一些非法参数,垃圾信息,或者是网站登录的验证码。
(主要总结 : 依赖容器,过滤非法参数和编码。)
在我们的老的项目中,配置是这样的:
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <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> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
不过只看配置文件,大体能看出,拦截器的配置是需要mapping的,也就是针对什么URI来进行不同的拦截,默认的话可以对全部路径进行拦截。
然后看拦截器是指定了编码格式,比如UTF-8。
一种实现:(来自博主:https://blog.csdn.net/javageektech/article/details/94250382)
大体上过滤器还是用来验证登录验证码用的,我们项目都没有配置过滤器,因为登录比较简单。
public class CaptchaFilter implements Filter { public void init(FilterConfig config) throws ServletException { } public void destroy() { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String servletPath = request.getServletPath(); //获取验证码 if(servletPath.matches("/captcha.jpg")) { response.setContentType("image/jpeg"); //禁止图像缓存。 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); //参数:宽、高、字符数、干扰量 CaptchaProductor vCode = new CaptchaProductor(70,30,4,75); //根据token保存验证码内容 CaptchaBean bean = new CaptchaBean(); bean.setCaptcha(vCode.getCode()); bean.setCreateTime(new Date()); HttpSessionUtils.setSessionValue(request, "sessionCaptcha", bean); vCode.write(response.getOutputStream()); return; } }}class CaptchaFilter implements Filter { public void init(FilterConfig config) throws ServletException { } public void destroy() { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String servletPath = request.getServletPath(); //获取验证码 if(servletPath.matches("/captcha.jpg")) { response.setContentType("image/jpeg"); //禁止图像缓存。 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); //参数:宽、高、字符数、干扰量 CaptchaProductor vCode = new CaptchaProductor(70,30,4,75); //根据token保存验证码内容 CaptchaBean bean = new CaptchaBean(); bean.setCaptcha(vCode.getCode()); bean.setCreateTime(new Date()); HttpSessionUtils.setSessionValue(request, "sessionCaptcha", bean); vCode.write(response.getOutputStream()); return; } } }
过滤器的实现可以通过实现 Filter 接口或者继承 Spring 的
org.springframework.web.filter.OncePerRequestFilter
来实现。5.4 拦截器与过滤器的区别
过滤器就是筛选出你要的东西,比如requeset中你要的那部分(筛选)
拦截器在做安全方面用的比较多,比如终止一些流程(请求进入的再次拦截)过滤器:
在实现上基于函数回调,可以对几乎所有请求进行过滤;
缺点是一个过滤器实例只能在容器初始化时调用一次;
使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。
拦截器:
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架;
在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用;
缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理;
由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。总结:
拦截器是基于java的反射机制的,而过滤器是基于函数回调。
拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
拦截器只能对action请求起作用(进入controller的),而过滤器则可以对几乎所有的请求起作用(包括静态页面)。
拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
5.5 监听器
监听器的作用是监听一些事件的发生从而进行一些操作,比如监听ServletContext,HttpSession的创建,销毁,从而执行一些初始化加载配置文件的操作,
当Web容器启动后,Spring的监听器会启动监听,监听是否创建ServletContext的对象,如果发生了创建ServletContext对象这个事件(当web容器启动后一定会生成一个ServletContext对象,所以监听事件一定会发生),ContextLoaderListener类会实例化并且执行初始化方法,将spring的配置文件中配置的bean注册到Spring容器中,
监听的操作是读取WEB-INF/applicationContext.xml,但是我们可以在web.xml中配置多个需要读取的配置文件,如下方所示,读取完成后所有的配置文件中的bean都会注册到spring容器中。
比如监听 ServletContext对象:
public void contextInitialized(ServletContextEvent event); public void contextDestoryed(ServletContextEvent event);
监听HttpSessionListener 对象:
publicvoid sessionCreated(HttpSessionEvent event); publicvoid sessionDestoryed(HttpSessionEvent event);
监听HttpRequestListener 对象:
public void requestinitialized(ServletRequestEvent event); public void requestDestoryed(ServletRequestEvent event);
web.xml的文件配置:
<listener> <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class> </listener> <!--<listener>--> <!--<listener-class>--> <!--org.springframework.web.util.IntrospectorCleanupListener</listener-class>--> <!--</listener>--> <!-- 加载通用的bean --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:xxx-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> </listener> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener>
上述配置提到的:HttpSessionEventPublisher 和ContextLoaderListener 就是监听器的一部分功能。
比如mvc项目自己定义监听器:
<listener> <listener-class>listener.MyListener</listener-class> </listener>
5.6 拦截器与过滤器的使用场景
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);(项目中拦截器记录了时间)
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如hibernate,在进入处理器打开Session,在完成后关闭Session。
(这个暂时没用到)拦截器是AOP的一种实现,底层通过动态代理模式完成。(动态代理面试必问)
-
控制过滤器Filter执行顺序
2021-12-08 10:24:14通过web.xml中控制filter-mapping的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行 <!-- 用户登录检测过滤器 --> <filter> <filter-... -
jenkins构建多个项目执行顺序设置
2018-07-06 15:37:00,有两个构建项目,posWeb是个web项目,welife是接口项目。 由于接口项目数据会影响posWeb执行。那么,就要设置,先执行welife项目。 配置如下: 由于posWeb是ui项目, 在执行过程中需要前台执行: 1.不使用... -
JavaWeb项目 Web.xml文件详解(启动顺序)
2021-12-26 20:36:21当启动一个WEB项目的时候,容器(比如Tomcat等),首先会读取项目web.xml配置文件里的配置,如果这一步骤不出错且完成之后,项目才能正常启动起来 1、在启动Web项目时,容器(如Tomcat)会首先读web.xml配置文件中的... -
filter的执行顺序是怎样的?
2020-12-21 16:25:541.引言我们在编写javaweb程序的时候,时常会用filter这个组件...servlet3.0以前我们只能通过web.xml的方式配置filter,并且多个filter的执行顺序是根据你web.xml中书写顺序来决定的.servlet3.0以后,提供了注解的方式注... -
SSM框架运行原理web.xml执行顺序
2018-06-29 13:54:56ssm框架 中web.xml执行顺序 1. <!–spring 的监听器–> <listener-class>org.springframework.web.context.ContextLoaderListener 2 <!– spring 主配置文件的 路径 和名字 –> <param-name>... -
多个过滤器的执行顺序
2019-12-10 20:23:39一个目标资源可以指定多个过滤器,过滤器的执行顺序是在web.xml文件中的部署顺序。 我们演示一下: 我们建立两个filter: AFilter: public void doFilter(ServletRequest request, ServletResponse response, ... -
web项目中的监听器,过滤器以及自定义servlet的执行顺序
2018-02-12 08:32:32转载自这篇文章可以看到web容器一启动就会实例化监听器的contextInitialized(ServletContextEvent event)方法,然后是过滤器的init()方法,最后在用户访问web应用的 时候会先执行过滤器的doFilter()方法,以及过滤... -
springboot项目启动后,执行代码顺序
2020-04-21 14:38:40springboot项目启动后,执行代码 SpringApplication的run方法下的 this.refreshContext(context); 执行后,执行继承ApplicationListener接口的类下的contextRefreshedEvent ```java @Component public class ... -
web项目启动时执行方法的实现方式
2018-11-24 11:40:09web项目启动的时执行方法,实现有好多种,可以分为2大类: 1.使用web自带的: (1)使用servlet,但是他不能使用spring 的bean 还需要手动获取,比较麻烦. (2)创建一个类实现ServletContextListener 接口,实现... -
springBoot 项目集成Mybatis,原有flyway不执行,项目启动报错;Flyway和MybatisPlus执行顺序
2022-04-13 22:51:24项目从jpa过渡到mybatis,代码整合之后,使用新的数据库连接,项目启动报错,未看到flyway等打印的日志信息,且数据库未生成数据。 报错大概为找不到对应表 org.springframework.context.... -
asp.net core 3.1学习笔记——启动执行顺序
2020-02-05 21:23:51一、准备环境: 1.开发工具:Microsoft Visual ...二、创建项目,选择WebAPI: 项目结构如下: 然后对里面每个对象方法添加对应名称的控制台输出语句,改造如下: Program.cs文件内容分别如下: using Sys... -
web-fragment 中的执行顺序
2018-03-29 23:28:13最近在一个decouple的项目中引入了web-fragment.xml, 遇到了一些问题,比较好玩,记录下。web-fragment.xml 是servlet 3.0 以后引入的,它也是用来提供web部署描述的,功能上跟web.xml是一模一样的。不一样的地方是... -
web项目启动就执行方法的几种方式
2019-09-03 17:41:521、方法加@PostConstruct2、实现CommandLineRunner接口,复写run方法 , 如果需要控制多个程序的执行是顺序 可以加@order注解3、实现ApplicationRunner接口 这个和 CommandLineRunner 基本一样 , 区别是:... -
拦截器(Interceptor)和过滤器(Filter)的执行顺序和区别
2021-07-29 02:59:33} } 6、控制执行顺序不同 实际开发过程中,会出现多个过滤器或拦截器同时存在的情况,不过,有时我们希望某个过滤器或拦截器能优先执行,就涉及到它们的执行顺序。 过滤器用@Order注解控制执行顺序,通过@Order控制... -
配置了多个Filter过滤器,它们的执行顺序是怎么样的?
2020-12-31 14:57:59一、执行顺序:如果有两个过滤器:过滤器1和过滤器2 1. request请求 1. 过滤器1 2. 过滤器2 2. 访问目标资源 3. 资源执行 3. response响应 4. 过滤器2 5. 过滤器1 二、过滤器先后顺序问题: 1.注解配置:按照... -
javaweb项目,过滤器的配置方式是注解@WebFilter时,过滤链filter执行顺序的控制方法!
2018-10-22 22:57:48当过滤器用web.xml配置时,控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如“用户登录检查过滤器”会比“接口日志过滤器”先执行,这种方式一搜一大堆。... -
Spring 执行顺序:PostProcessor 接口
2019-08-29 21:12:43由于这个配置会影响其他测试的执行顺序(EnvironmentPostProcessor 肯定是第一个),所以本项目中注释了上述配置。 该接口比所有其他 PostProcessor 执行的都早,由于接口特殊,这里不再继续往下进行分析。 -
在web项目启动时执行某个方法
2018-03-31 22:32:38在web项目启动时执行某个方法的几种方式:指定init-method的Bean执行、实现spring的Bean后置处理器执行、Servlet的监听器执行、Servlet的过滤器执行、Servlet执行。1、实现Servlet监听器接口ServletContextListener...