Spring注解驱动开发-----servlet3.0springmvc

Posted alimayun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring注解驱动开发-----servlet3.0springmvc相关的知识,希望对你有一定的参考价值。

ServletContainerInitializer

Shared libraries(共享库) / runtimes pluggability(运行时插件能力)

1、Servlet容器启动会扫描,当前应用里面每一个jar包的
ServletContainerInitializer的实现
2、提供ServletContainerInitializer的实现类;
必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer
文件的内容就是ServletContainerInitializer实现类的全类名;

示例

1、MyServletContainerInitializer

package com.atguigu.servlet;

import java.util.EnumSet;
import java.util.Set;

import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.HandlesTypes;

import com.atguigu.service.HelloService;

//容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
//传入感兴趣的类型;
@HandlesTypes(value=HelloService.class)
public class MyServletContainerInitializer implements ServletContainerInitializer 

    /**
     * 应用启动的时候,会运行onStartup方法;
     * 
     * Set<Class<?>> arg0:感兴趣的类型的所有子类型;
     * ServletContext arg1:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
     */
    @Override
    public void onStartup(Set<Class<?>> arg0, ServletContext sc) throws ServletException 
        // TODO Auto-generated method stub
        System.out.println("感兴趣的类型:");
        for (Class<?> claz : arg0) 
            System.out.println(claz);
        
    

2、配置

技术图片

需要新建META-INF/services文件夹,并且文件名为javax.servlet.ServletContainerInitializer,文件内容就为MyServletContainerInitializer的包路径

这样应用启动的时候,会运行onStartup方法,会将所有的HelloService拿到。

3、额外添加servlet、filter以及listener组件

修改MyServletContainerInitializer:

package com.atguigu.servlet;

import java.util.EnumSet;
import java.util.Set;

import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.HandlesTypes;

import com.atguigu.service.HelloService;

//容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
//传入感兴趣的类型;
@HandlesTypes(value=HelloService.class)
public class MyServletContainerInitializer implements ServletContainerInitializer 

    /**
     * 应用启动的时候,会运行onStartup方法;
     * 
     * Set<Class<?>> arg0:感兴趣的类型的所有子类型;
     * ServletContext arg1:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
     * 
     * 1)、使用ServletContext注册Web组件(Servlet、Filter、Listener)
     * 2)、使用编码的方式,在项目启动的时候给ServletContext里面添加组件;
     *         必须在项目启动的时候来添加;
     *         1)、ServletContainerInitializer得到的ServletContext;
     *         2)、ServletContextListener得到的ServletContext;
     */
    @Override
    public void onStartup(Set<Class<?>> arg0, ServletContext sc) throws ServletException 
        // TODO Auto-generated method stub
        System.out.println("感兴趣的类型:");
        for (Class<?> claz : arg0) 
            System.out.println(claz);
        
        
        //注册组件  ServletRegistration  
        ServletRegistration.Dynamic servlet = sc.addServlet("userServlet", new UserServlet());
        //配置servlet的映射信息
        servlet.addMapping("/user");
        
        
        //注册Listener
        sc.addListener(UserListener.class);
        
        //注册Filter  FilterRegistration
        FilterRegistration.Dynamic filter = sc.addFilter("userFilter", UserFilter.class);
        //配置Filter的映射信息
        filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
        
    

4、UserServlet

package com.atguigu.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class UserServlet extends HttpServlet 
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        // TODO Auto-generated method stub
        resp.getWriter().write("tomcat...");
    

5、UserFilter

package com.atguigu.servlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class UserFilter implements Filter 

    @Override
    public void destroy() 
        // TODO Auto-generated method stub
        
    

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
            throws IOException, ServletException 
        // 过滤请求
        System.out.println("UserFilter...doFilter...");
        //放行
        arg2.doFilter(arg0, arg1);
        
    

    @Override
    public void init(FilterConfig arg0) throws ServletException 
        // TODO Auto-generated method stub
        
    

6、UserListener

package com.atguigu.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * 监听项目的启动和停止
 * @author lfy
 *
 */
public class UserListener implements ServletContextListener 

    
    //监听ServletContext销毁
    @Override
    public void contextDestroyed(ServletContextEvent arg0) 
        // TODO Auto-generated method stub
        System.out.println("UserListener...contextDestroyed...");
    

    //监听ServletContext启动初始化
    @Override
    public void contextInitialized(ServletContextEvent arg0) 
        // TODO Auto-generated method stub
        ServletContext servletContext = arg0.getServletContext();
        System.out.println("UserListener...contextInitialized...");
    

Servlet3.0整合springMVC

接入分析

1、web容器在启动的时候,会扫描每个jar包下的META-INF/services/javax.servlet.ServletContainerInitializer
2、加载这个文件指定的类SpringServletContainerInitializer
3、spring的应用一启动会加载感兴趣的WebApplicationInitializer接口的下的所有组件;
4、并且为WebApplicationInitializer组件创建对象(组件不是接口,不是抽象类)
  1)、AbstractContextLoaderInitializer:创建根容器;createRootApplicationContext();
  2)、AbstractDispatcherServletInitializer:
      创建一个web的ioc容器;createServletApplicationContext();
      创建了DispatcherServlet;createDispatcherServlet();
      将创建的DispatcherServlet添加到ServletContext中;
      getServletMappings();
  3)、AbstractAnnotationConfigDispatcherServletInitializer:注解方式配置的DispatcherServlet初始化器
      创建根容器:createRootApplicationContext()
      getRootConfigClasses();传入一个配置类
      创建web的ioc容器: createServletApplicationContext();
      获取配置类;getServletConfigClasses();

总结:
以注解方式来启动SpringMVC;继承AbstractAnnotationConfigDispatcherServletInitializer;实现抽象方法指定DispatcherServlet的配置信息;-----通过看源码,得出这个逻辑

===========================
定制SpringMVC;
1)、@EnableWebMvc:开启SpringMVC定制配置功能;
<mvc:annotation-driven/>;

2)、配置组件(视图解析器、视图映射、静态资源映射、拦截器。。。)
extends WebMvcConfigurerAdapter

整合 

1、MyWebAppInitializer

package com.atguigu;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.atguigu.config.AppConfig;
import com.atguigu.config.RootConfig;

//web容器启动的时候创建对象;调用方法来初始化容器以前前端控制器
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer 

    //获取根容器的配置类;(Spring的配置文件)   父容器;
    @Override
    protected Class<?>[] getRootConfigClasses() 
        // TODO Auto-generated method stub
        return new Class<?>[]RootConfig.class;
    

    //获取web容器的配置类(SpringMVC配置文件)  子容器;
    @Override
    protected Class<?>[] getServletConfigClasses() 
        // TODO Auto-generated method stub
        return new Class<?>[]AppConfig.class;
    

    //获取DispatcherServlet的映射信息
    //  /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp;
    //  /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的;
    @Override
    protected String[] getServletMappings() 
        // TODO Auto-generated method stub
        return new String[]"/";
    

2、RootConfig-----spring容器配置类

package com.atguigu.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

//Spring的容器不扫描controller;父容器
@ComponentScan(value="com.atguigu",excludeFilters=
        @Filter(type=FilterType.ANNOTATION,classes=Controller.class)
)
public class RootConfig 

3、AppConfig-----springmvc容器配置类

package com.atguigu.config;


import java.util.List;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.atguigu.controller.MyFirstInterceptor;

//SpringMVC只扫描Controller;子容器
//useDefaultFilters=false 禁用默认的过滤规则;
@ComponentScan(value="com.atguigu",includeFilters=
        @Filter(type=FilterType.ANNOTATION,classes=Controller.class)
,useDefaultFilters=false)
@EnableWebMvc
public class AppConfig  extends WebMvcConfigurerAdapter  

还记得之前在使用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:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--将SpringMVC处理不了的请求交给tomcat;静态资源 就可以访问 -->
    <mvc:default-servlet-handler/>
    <!-- SpringMVC的高级功能开启 -->
    <mvc:annotation-driven />
    
    <!-- <mvc:interceptors>
    
    </mvc:interceptors>
    <mvc:view-controller path=""/> -->

</beans>

通过注解也可以实现:

定制SpringMVC;
1)、@EnableWebMvc:开启SpringMVC定制配置功能;
<mvc:annotation-driven/>;

2)、配置组件(视图解析器、视图映射、静态资源映射、拦截器。。。)
extends WebMvcConfigurerAdapter

修改AppConfig

package com.atguigu.config;


import java.util.List;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.atguigu.controller.MyFirstInterceptor;

//SpringMVC只扫描Controller;子容器
//useDefaultFilters=false 禁用默认的过滤规则;
@ComponentScan(value="com.atguigu",includeFilters=
        @Filter(type=FilterType.ANNOTATION,classes=Controller.class)
,useDefaultFilters=false)
@EnableWebMvc
public class AppConfig  extends WebMvcConfigurerAdapter  

    //定制
    
    //视图解析器
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) 
        // TODO Auto-generated method stub
        //默认所有的页面都从 /WEB-INF/ xxx .jsp
        //registry.jsp();
        registry.jsp("/WEB-INF/views/", ".jsp");
    
    
    //静态资源访问
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) 
        // TODO Auto-generated method stub
        configurer.enable();//-----相当于<mvc:default-servlet-handler/>,把处理不了的请求交给tomcat
    
    
    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) 
        // TODO Auto-generated method stub
        //super.addInterceptors(registry);
        registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**");
    

MyFirstInterceptor:

package com.atguigu.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyFirstInterceptor implements HandlerInterceptor 

    //目标方法运行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception 
        // TODO Auto-generated method stub
        System.out.println("preHandle..."+request.getRequestURI());
        return true;
    

    //目标方法执行正确以后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception 
        // TODO Auto-generated method stub
        System.out.println("postHandle...");

    

    //页面响应以后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception 
        // TODO Auto-generated method stub
        System.out.println("afterCompletion...");
    

 

 

以上是关于Spring注解驱动开发-----servlet3.0springmvc的主要内容,如果未能解决你的问题,请参考以下文章

Spring注解驱动开发-AOPTx和Servlet3.0

Spring注解驱动开发之web

Spring全注解开发----Servlet 3.0

重新学习Spring注解——servlet3.0

23spring注解学习——servlet3.0异步和spring的异步

servlet3.0全注解spring整合shiro