Spring注解驱动开发之web
2020-12-13 03:25
                         标签:etl   通过   配置filter   block   text   ini   驱动开发   sign   clu    前言:现今SpringBoot、SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解、原理,比如@Conditional、@Import、@EnableXXX等。如果掌握这些底层原理、注解,那么我们对这些高层框架就能做到高度定制,使用的游刃有余       在servlet3.0之前的话,我们要添加Servlet、Filter、Listener都需要在web.xml中注册,而在servlet3.0添加了注解支持:     @WebServlet: 用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet,如:         @WebFilter: 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器;     @WebListener:该注解用于将类声明为监听器,被 @WebListener 标注的类必须实现对应的监听器接口       @WebInitParam:该注解通常不单独使用,而是配合 @WebServlet 或者 @WebFilter 使用。它的作用是为 Servlet 或者过滤器指定初始化参数,这等价于 web.xml 中      在使用实现了servlet3.0规范的servlet容器中,Servlet容器启动会扫描当前应用里面每一个jar包的ServletContainerInitializer的实现,前提是ServletContainerInitializer的实现类必须绑定在META-INF/services/javax.servlet.ServletContainerInitializer中,文件的内容就是ServletContainerInitializer实现类的全类名          使用该特性,现在我们可以在不修改已有 Web 应用的前提下,只需将按照一定格式打成的 JAR 包放到 WEB-INF/lib 目录下,即可实现新功能的扩充(比如注册三大组件),不需要额外的配置;     在之前使用SpringMVC时,很多时候都是在web.xml中配置的方式来启动,而从SpringMVC 3.1开始就使用了servlet3.0的插件机制,可通过配置类的方式来启动SpringMVC          在spring的web模块的jar包下存在META-INF/services/javax.servlet.ServletContainerInitializer,该文件中指定ServletContainerInitializer的实现类为SpringServletContainerInitializer,可知在web容启动时会加载这个类,来看看这个类:    接下来看看SpringServletContainerInitializer使用@HandlesTypes引入的WebApplicationInitializer接口(只定义了一个onStartup方法)的子类:        AbstractContextLoaderInitializer主要的功能:   调用创建createRootApplicationContext()创建根容器,   注册了监听器ContextLoaderListener(extends ContextLoader implements ServletContextListener)   AbstractDispatcherServletInitializer 的主要功能:   创建一个web的ioc容器:createServletApplicationContext();   创建了DispatcherServlet:createDispatcherServlet();   将创建的DispatcherServlet添加到ServletContext中,并设置路径映射等;   AbstractAnnotationConfigDispatcherServletInitializer (注解方式配置的DispatcherServlet初始化器) 主要作用:   创建根容器:createRootApplicationContext(),调用getRootConfigClasses()获取配置类   创建web的ioc容器: createServletApplicationContext(),调用getServletConfigClasses()获取配置类     上面我们分析了三个抽象类的功能,最终需要我们需要继承AbstractAnnotationConfigDispatcherServletInitializer,实现对应抽象方法来指定DispatcherServlet的配置信息                                        Spring注解驱动开发之web 标签:etl   通过   配置filter   block   text   ini   驱动开发   sign   clu    原文地址:https://www.cnblogs.com/qzlcl/p/11074954.html一、servlet3.0规范
1、新增的注解支持
@WebServlet(urlPatterns = {"/simple"}, asyncSupported = true, 
loadOnStartup = -1, name = "SimpleServlet", displayName = "ss", 
initParams = {@WebInitParam(name = "username", value = "tom")} 
) 
public class SimpleServlet extends HttpServlet{ … }
2、runtimes pluggability(运行时插件能力)
//容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
//传入感兴趣的类型;
@HandlesTypes(value={HelloService.class})
public class MyServletContainerInitializer implements ServletContainerInitializer {
    /**
     * 应用启动的时候,会运行onStartup方法;
     * 
     * Set

二、SpringMVC注解开发
 

1、SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)//容器启动的时候会将WebApplicationInitializer类型下面的子类(实现类,子接口等)传递过来
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    //webAppInitializerClasses就是WebApplicationInitializer类型
       @Override
    public void onStartup(Set
     
        AnnotationAwareOrderComparator.sort(initializers);
     //遍历执行initializers集合中WebApplicationInitializer.onStartup(servletContext)方法
        for (WebApplicationInitializer initializer : initializers) {
            initializer.onStartup(servletContext);
        }
    }
}    
2、AbstractContextLoaderInitializer
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
    /** Logger available to subclasses */
    protected final Log logger = LogFactory.getLog(getClass());
  //该方法会在web容器启动时SpringServletContainerInitializer.onStartup中被调用
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
      //注册加载上下文的监听器
        registerContextLoaderListener(servletContext);
    }
    
    protected void registerContextLoaderListener(ServletContext servletContext) {
    //调用createRootApplicationContext()创建根容器,需要具体的实现类去实现该抽象方法获取根容器
        WebApplicationContext rootAppContext = createRootApplicationContext();
        if (rootAppContext != null) {
       //创建监听器,并将根容器传入
            ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
       //设置上下文初始化器
            listener.setContextInitializers(getRootApplicationContextInitializers());
       //添加监听器
            servletContext.addListener(listener);
        }
        else {
            logger.debug("No ContextLoaderListener registered, as " +
                    "createRootApplicationContext() did not return an application context");
        }
    }
    //抽象方法,子类必须实现
    protected abstract WebApplicationContext createRootApplicationContext();
   //默认返回空 子类可重写 
    protected ApplicationContextInitializer>[] getRootApplicationContextInitializers() {
        return null;
    }
}3、AbstractDispatcherServletInitializer:
public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
    /**
     * The default servlet name. Can be customized by overriding {@link #getServletName}.
     */
    public static final String DEFAULT_SERVLET_NAME = "dispatcher";
   //重写了AbstractContextLoaderInitializer.onStartup(ServletContext)
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
     //维持父类的实现
        super.onStartup(servletContext);
     //添加了注册DispatcherServlet的步骤
        registerDispatcherServlet(servletContext);
    }
   
    protected void registerDispatcherServlet(ServletContext servletContext) {
        String servletName = getServletName();
        Assert.hasLength(servletName, "getServletName() must not return empty or null");
     //调用createServletApplicationContext()创建web的ioc容器(管理Controller等springmvc的组件),需要子类去实现该抽象方法去获取web容器
        WebApplicationContext servletAppContext = createServletApplicationContext();
        Assert.notNull(servletAppContext,
                "createServletApplicationContext() did not return an application " +
                "context for servlet [" + servletName + "]");
     //创建了前端控制器DispatcherServlet
        FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
        dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
     //使用servletContext添加DispatcherServlet
        ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
        Assert.notNull(registration,
                "Failed to register servlet with name ‘" + servletName + "‘." +
                "Check if there is another servlet registered under the same name.");
        registration.setLoadOnStartup(1);
     //具体的路径映射规则需要子类实现getServletMappings()
        registration.addMapping(getServletMappings());
        registration.setAsyncSupported(isAsyncSupported());
        Filter[] filters = getServletFilters();
        if (!ObjectUtils.isEmpty(filters)) {
            for (Filter filter : filters) {
                registerServletFilter(servletContext, filter);
            }
        }
        customizeRegistration(registration);
    }
    
    protected String getServletName() {
        return DEFAULT_SERVLET_NAME;
    }
   
    protected abstract WebApplicationContext createServletApplicationContext();
   
    protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
        return new DispatcherServlet(servletAppContext);
    }
    
    protected ApplicationContextInitializer>[] getServletApplicationContextInitializers() {
        return null;
    }
    
    protected abstract String[] getServletMappings();
    
    protected Filter[] getServletFilters() {
        return null;
    }
    
    protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
        String filterName = Conventions.getVariableName(filter);
        Dynamic registration = servletContext.addFilter(filterName, filter);
        if (registration == null) {
            int counter = -1;
            while (counter == -1 || registration == null) {
                counter++;
                registration = servletContext.addFilter(filterName + "#" + counter, filter);
                Assert.isTrue(counter ,
                        "Failed to register filter ‘" + filter + "‘." +
                        "Could the same Filter instance have been registered already?");
            }
        }
        registration.setAsyncSupported(isAsyncSupported());
        registration.addMappingForServletNames(getDispatcherTypes(), false, getServletName());
        return registration;
    }
    private EnumSet4、AbstractAnnotationConfigDispatcherServletInitializer
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
        extends AbstractDispatcherServletInitializer {
   //实现了AbstractContextLoaderInitializer.createRootApplicationContext(),创建根容器
    @Override
    protected WebApplicationContext createRootApplicationContext() {
     //获取根容器的配置类
        Class>[] configClasses = getRootConfigClasses();
        if (!ObjectUtils.isEmpty(configClasses)) {
        //创建ioc容器
            AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
       //注册组件
            rootAppContext.register(configClasses);
            return rootAppContext;
        }
        else {
            return null;
        }
    }
   //实现了AbstractDispatcherServletInitializer.createServletApplicationContext(),创建web的ioc容器
    @Override
    protected WebApplicationContext createServletApplicationContext() {
     
        AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
     //获取web ioc容器的配置类
        Class>[] configClasses = getServletConfigClasses();
        if (!ObjectUtils.isEmpty(configClasses)) {
       //
            servletAppContext.register(configClasses);
        }
        return servletAppContext;
    }
   //抽象方法 子类实现 返回根容器的配置类
    protected abstract Class>[] getRootConfigClasses();
  //抽象方法 子类实现 返回web ioc容器的配置类   
    protected abstract Class>[] getServletConfigClasses();
}5、以注解方式来启动SpringMVC:
//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[]{"/"};
    }
}
     
上一篇:Unity Shader的形式