springmvc工作流程 + 过滤器-拦截器-监听器

目录

 

1、工作流程

2、配置流程

3、过滤器、拦截器

3.1、过滤器

3.2、拦截器

3.3、总结

4、监听器


1、工作流程

图一:

 

     执行流程:

  1. 客户端请求被DispatcherServlet(前端控制器)接收
  2. DispatcherServlet请求HandlerMapping查询Handler
  3. HandlerMapping根据请求URL查找Handler,将Handler和HandlerInterceptor以HandlerExecutionChain的形式一并返回给DispatcherServlet
  4. DispatcherServlet请求HandlerAdapter执行Handler
  5. HandlerAdapter调用Handler的方法做业务逻辑处理
  6. HandlerAdapter处理完Handler会生成一个ModelAndView对象
  7. 将ModelAndView对象返回给DispatcherServlet
  8. DispatcherServlet将获取的ModelAndView对象传给ViewResolver视图解析器,请求进行视图解析
  9. ViewResolver将逻辑视图解析成物理视图View,返回给DispatcherServlet
  10. DispatcherServlet根据View进行视图渲染(将模型数据填充到视图中)
  11. DispatcherServlet将渲染后的视图响应给客户端

图二:

 

2、配置流程

step1:配置servlet.DispatcherServlet文件

init-param的作用是在启动servlet启动时规定其地地址及名称去搜寻其springmvc配置文件

	<!-- springmvc的前端控制器 -->
	<servlet>
		<servlet-name>comqing-manager</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
		<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>comqing-manager</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

step2:配置handlermapping

  在springmvc.xml中配置文件

附:handlermapping的三种方式(作用就是找controller)
1、默认方式BeanNameUrlHandlerMapping,根据benan的属性name值寻找对应的controller(class)

2、ControllerClassNameHandlerMapping,根据controller名称进行对应,注意命名规则,地址栏上写最后的类名要全部小写,如果最后是controller,可以省略,也可以首字母不区分大小写

3、simpleurlHandlermappering,根据property的props的prop进行id的定位id

一般handlermapping一般采用默认方式,下面“comqing-manager”对应step1中的servlet-name:

<mvc:default-servlet-handler default-servlet-name="comqing-manager"/> 

同事要配置扫描包的位置

	<!-- 对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
	<context:component-scan base-package="com.comqing.controller" />

step3:配置视图解析器

	<!-- 用于Spring MVC视图解析 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/pages/" />
		<property name="suffix" value=".jsp" />
	</bean>

step4:根据需求配置其他

包括拦截器、资源映射、定义文件上传解析器、properties配置文件、SwaggerConfig配置类等

    <!-- 自定义拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/api/**" />
			<bean class="com.comqing.interceptor.CrmInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

    <!-- 资源映射 -->
	<mvc:resources location="/WEB-INF/css/" mapping="/css/**" />
	<mvc:resources location="/WEB-INF/js/" mapping="/js/**" />


    <!-- 定义文件上传解析器 -->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设定默认编码 -->
		<property name="defaultEncoding" value="UTF-8"></property>
		<!-- 设定文件上传的最大值5MB,5*1024*1024 -->
		<property name="maxUploadSize" value="5242880"></property>
	</bean>

   
	<!-- properties配置文件 -->
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations" value="classpath:resource/resource.properties" />
	</bean>

    
    <!--SwaggerConfig配置类注入 -->
	    <bean class="com.comqing.conf.SwaggerConfig" />
	    <!--配置swagger资源 拦截 -->
	    <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" />
	    <mvc:resources mapping="/webjars/**"
		location="classpath:/META-INF/resources/webjars/" />
    </beans>

   

3、过滤器、拦截器

3.1、过滤器

Filter是Spring框架中的一个过滤器,然而过滤器就是对其中请求的信息进行处理,然后再传送。Filter不像Servlet,它不能产生一个请求或者响应,它只能修改对某一资源的请求,或修改从某一的响应。它实现了javax.servlet.Filter接口的服务端程序,主要作用是过滤字符编码、做一些业务逻辑判断,主要用于对用户请求进行预处理。

Filter是基于函数回调(doFilter()方法)的。

web.xml配置

<!-- 设置过滤器 !-->
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.sxkj.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/user/*</url-pattern>
    </filter-mapping>

定义过滤器LoginFilter

过滤器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驱动

public class LoginFilter implements Filter {

    //init: 用于完成Filter 的初始化
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化...");
        chain.doFilter(request, response);
    }

    //doFilter:实现过滤功能,该方法就是对每个请求及响应增加的额外处理。
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器doFilter...");

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;    
    }

    //destroy:用于Filter 销毁前,完成某些资源的回收
    @Override
    public void destroy() {
        System.out.println("过滤器销毁...");
    }
}

在方法doFilter中的chain.doFilter(request, response)最终是调用Servlet的doService()方法

3.2、拦截器

对controller起作用

它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

Interceptor则是基于Java反射的(AOP思想)

springmvc.xml中配置

 <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/user/**"/>
            <bean class="com.sxkj.interceptor.LoginIntercepter"/>
        </mvc:interceptor>
    </mvc:interceptors>

下面代码执行流程:

  • 1.程序先执行preHandle()方法,如果该方法的返回值为true,则程序会继续向下执行处理器中的方法,否则将不再向下执行。
  • 2.在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应。
  • 3.在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。
/**
 * 用户登录状态拦截器
 */
public class LoginIntercepter111 implements HandlerInterceptor {
    /**
     * 该方法将在Controller处理之前进行调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        return true;
    }

    /**
     * @Description  该方法将在Controller处理之后进行调用
     **/
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    /**
     * @Description  处理完请求后带调用
     **/
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }

}

 

3.3、总结

过滤器的运行是依赖于servlet容器的,跟springmvc等框架并没有关系。并且多个过滤器的执行顺序跟web.xml文件中定义的先后关系有关

拦截器的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关。

如下是过滤器与拦截器合并执行的流程

Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用。

拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),再细的话,建议用interceptor。

 

4、监听器

Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次。主要作用是:做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。

实现:

首先在web.xml中配置:


<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
 
<listener>
    <listener-class>example.ConfigListener</listener-class>
</listener>

java代码:

public class ConfigListener implements ServletContextListener {
 
    @Autowired
    private ConfigService configService;
     
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        configService.initConfig();
    }
 
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

  注意上面代码configService是取不到的:

项目启动时抛出空指针异常!ConfigService实例并没有成功注入。这是为什么呢?要理解这个问题,首先要区分Listener的生命周期和spring管理的bean的生命周期。

(1)Listener的生命周期是由servlet容器(例如tomcat)管理的,项目启动时上例中的ConfigListener是由servlet容器实例化并调用其contextInitialized方法,而servlet容器并不认得@Autowired注解,因此导致ConfigService实例注入失败。

(2)而spring容器中的bean的生命周期是由spring容器管理的。

那么该如何在spring容器外面获取到spring容器bean实例的引用呢:

@Override
    public void contextInitialized(ServletContextEvent sce) {   
        ConfigService configService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(ConfigService.class);
        configService.initConfig();
    }

 

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值