Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用

Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

在 Servlet 3.0 时支持注解启动,不再需要 web.xml 配制文件。详见《Servlet 3.0 规范(二)注解规范》:https://www.cnblogs.com/binarylei/p/10204208.html

一、Servlet 3.0 与 Spring MVC 整合

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException { List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// WebApplicationInitializer 的实现类
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
} catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
} if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
} // 执行 onStartup
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
} }

Spring MVC 启动时会调用 WebApplicationInitializer 实现类的 onStartup 方法启动 WEB 容器。WebApplicationInitializer 的继承关系如下:

WebApplicationInitializer
|- AbstractContextLoaderInitializer
|- AbstractDispatcherServletInitializer
|- AbstractAnnotationConfigDispatcherServletInitializer
  • AbstractContextLoaderInitializer 创建 Root 根容器并注册 ContextLoaderListener,创建根容器由子类实现。核心方法:registerContextLoaderListener

  • AbstractDispatcherServletInitializer 创建 Servlet 容器,并注册 DispatcherServlet 和 Filete,创建根容器由子类实现。核心方法:registerDispatcherServlet

  • AbstractAnnotationConfigDispatcherServletInitializer 创建 Root 和 Servlet 容器。核心方法:createRootApplicationContext、createServletApplicationContext

断点调试,webAppInitializerClasses 有以下类,显然只有一个实现类 MyAbstractAnnotationConfigDispatcherServletInitializer 执行了 onStartup 方法。

0 = {Class@4467} "class org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer"
1 = {Class@4468} "class org.springframework.web.servlet.support.AbstractDispatcherServletInitializer"
2 = {Class@4469} "class org.springframework.web.server.adapter.AbstractReactiveWebInitializer"
3 = {Class@4470} "class org.springframework.web.context.AbstractContextLoaderInitializer"
4 = {Class@4471} "class com.github.binarylei.MyAbstractAnnotationConfigDispatcherServletInitializer"

二、WebMvcConfigurer 接管 xml 配置

(1) @EnableWebMvc

开启 Spring 高级功能,相当于 <mvc:annotation-driven/>

(2) WebMvcConfigurer

对应以前 XML 配置中的每一项,以 interceptors 为例,其余详见官方文档:Spring 注解配置类 WebMvcConfigurer(https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web.html#mvc-config)

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
}
}

以上代码相当于之前 XML 中的

<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/admin/**"/>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/secure/*"/>
<bean class="org.example.SecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

三、模拟 Spring Boot 将 WEB 打成 jar 包运行

Spring 官方文档注解配置

使用 tomcat7-maven-plugin 插件模拟 Spring Boot。

(1) WebApplicationInitializer 实现类

public class MyAbstractAnnotationConfigDispatcherServletInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer { // Root 容器配置
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
} // Servlet 容器配置
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MyServletConfig.class};
} // Servlet Mapping,取代 web.xml 中的 servlet-mapping 配置
protected String[] getServletMappings() {
return new String[]{"/"};
} // Filter 配置,取代 web.xml 中的 filter 配置
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("utf-8");
encodingFilter.setForceRequestEncoding(true);
encodingFilter.setForceResponseEncoding(true); return new Filter[]{encodingFilter};
}
} // 取代 spring-mvc.xml 配制
@Configuration
@ComponentScan(basePackages = "com.github.binarylei",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})
public class MyRootConfig {
} // 取代 spring-context.xml 配制
@Configuration
@ComponentScan(basePackages = "com.github.binarylei",
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})
public class MyServletConfig { @Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}

(2) tomcat7-maven-plugin 配制

tomcat7-maven-plugin 官网:http://tomcat.apache.org/maven-plugin-2.1/executable-war-jar.html

<packaging>war</packaging>
<properties>
<spring.version>5.1.0.RELEASE</spring.version> <project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>exec-war-only</goal>
</goals>
<phase>package</phase>
<configuration>
<path>/</path>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

(3) 运行

执行 mvn package 后生成了两个文件:spring-war-1.0.0.war 和 spring-war-1.0.0-war-exec.jar

# localhost:8080/
java -jar spring-war-1.0.0-war-exec.jar
# IDEA remote 调试时(suspend=y)
java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 spring-war-1.0.0-war-exec.jar

tomcat 启动远程时报错:https://www.aliyun.com/jiaocheng/1443062.html


每天用心记录一点点。内容也许不重要,但习惯很重要!

Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用的更多相关文章

  1. 2017.2.13 开涛shiro教程-第十二章-与Spring集成(二)shiro权限注解

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第十二章-与Spring集成(二)shiro权限注解 shiro注 ...

  2. Spring Aop(二)——基于Aspectj注解的Spring Aop简单实现

    转发地址:https://www.iteye.com/blog/elim-2394762 2 基于Aspectj注解的Spring Aop简单实现 Spring Aop是基于Aop框架Aspectj实 ...

  3. spring boot Swagger2(version=2.7.0) 注解@ApiImplicitParam的属性dataType值为”自定义泛型“应用

    注解: @ApiImplicitParams @ApiImplicitParam    name="需注解的API输入参数", value="接收参数的意义描述" ...

  4. Spring Cloud 升级之路 - 2020.0.x - 7. 使用 Spring Cloud LoadBalancer (2)

    本项目代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...

  5. Spring Cloud 升级之路 - 2020.0.x - 6. 使用 Spring Cloud LoadBalancer (1)

    本项目代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...

  6. Android注解使用之ButterKnife 8.0注解使用介绍

    前言: App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种 ...

  7. Servlet 3.0 规范(二)注解驱动和异步请求

    Servlet 3.0 规范(二)注解驱动和异步请求 在 Servlet 3.0 时支持注解启动,不再需要 web.xml 配制文件. 一.Servlet 3.0 组件 Servlet 容器的组件大致 ...

  8. Spring 3.0 注解注入详解

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  9. Spring注解开发系列VII --- Servlet3.0

    Servlet3.0简介 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用 ...

随机推荐

  1. AJAX简单实例

    越用AJAX越觉得它的强大.好用. 平常我们提交表单,是直接通过action属性,直接向后台提交数据. 我们也可以用AJAX向后台提交数据.例如: 这是一个表单,两个字段:notice,scort,保 ...

  2. mysql里max_allowed_packet的作用

    MySQL根据配置文件会限制Server接受的数据包大小.有时候大的插入和更新会受 max_allowed_packet 参数限制,导致写入或者更新失败. 查看目前配置: 代码如下: show VAR ...

  3. backdoor-factory

    启动backdoor-factory 寻找大于100字节的代码洞 执行的结果 查看适合的payload程序 iat_reverse_tcp_stager_threaded分片段注入方式 使用这种注入方 ...

  4. 通过DataTable获得表的主键

    转载http://www.cnblogs.com/hobe/archive/2005/10/07/249940.html 通过DataTable获得表的主键 很多情形下我们需要知道表的主键是什么.在A ...

  5. JAVA高精度模板

    刚开始还坚持用C++写高精来着,后来发现JAVA写高精方便太多了,所以也来学习一下JAVA高精度的模板. 参考:https://www.cnblogs.com/imzscilovecode/p/883 ...

  6. centos 配置Openssl并创建证书

    具体详情参考:http://wiki.centos.org/HowTos/Https 一.安装软件 yum install mod_ssl openssl 二.创建证书: # Generate pri ...

  7. CentOS systemctl命令

    systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起. 任务 旧指令 新指令 使某服务自动启动 chkconfig --level 3  ...

  8. js前端导出excel:json形式的导出

    第一中形式的导出:主要是表头对应主体数据,json形式的导出 js库文件名称 : table2excel.js这个js库文件是网上找的,并且自己根据自己业务需求把内容改了一下复制到 table2exc ...

  9. FZU-2150.FireGame.(BFS))

    本题大意:给出一个n * m的地,‘#’ 代表草, ‘.’代表陆地,每次选择这片地里的两片草,可选相等的草,选择的两片草初始状态为被燃状态,每一分钟被点燃的草会将身边的四连块点.问你需要对于给定的这片 ...

  10. 互联网进行限流策略的Semaphore信号量使用

    在Semaphore信号量非常适合高并发访问,新系统在上线之前,要对系统的访问量进行评估,当然这个值肯定不是随便拍拍脑袋就能想出来的,是经过以往的经验.数据.历年的访问量,已经推广力度进行一个合理的评 ...