Spring 注解驱动(二)WEB 注解开发

Spring 注解驱动(二)WEB 注解开发

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

一、基本使用

在 Servlet 3.0 时支持注解启动,不再需要 web.xml 配制文件。

1.1 Servlet 3.0 注解

Servlet 3.0 常用注解: @WebServlet @WebFilter @WebInitParam @WebListener

@WebServlet("/hello")
public class HelloServert extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("hello");
    }
}

1.2 ServletContainerInitializer

  1. Servlet 容器启动会扫描当前应用的每一个 jar 包 ServletContainerInitializer 的实现。
  2. 通过每个 jar 包下的 META-INFO/services/javax.servlet.ServletContainerInitializer 文件:

    com.github.binarylei.MyServletContainerInitializer

@HandlesTypes(HelloServert.class)
public class MyServletContainerInitializer implements ServletContainerInitializer {

    /**
     * @param c                 @HandlesTypes 指定,HelloServert 子类
     * @param ServletContext    注册三大组件(Servlet Filter Listener)
     */
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext ctx)
            throws ServletException {
        // 1. 处理感兴趣的类
        System.out.println(set);

        // 2.1. 注册 Servert
        ServletRegistration.Dynamic servlet = ctx.addServlet("myServlet", HelloServert.class);
        servlet.addMapping("/*");

        // 2.2. 注册 Listener
        ctx.addListener(MyServletContextListener.class);

        // 2.3. 注册 Filter
        FilterRegistration.Dynamic filter = ctx.addFilter("myFileter", MyFilter.class);
        filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),
                true, "/*");
    }
}

在 Servlet 3.0 时支持注解启动,其中 ServletContainerInitializer 和 HandlesTypes 都是 Servlet 3.0 的规范。

  • ServletContainerInitializer 只有一个方法 onStartup
  • HandlesTypes 感兴趣的类,启动时会通过 onStartup 传递给 clazzs 参数。HandlesTypes 会找到 HelloServert 所有的子类(不包括 HelloServert 自己)

1.3 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 = {[email protected]} "class org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer"
1 = {[email protected]} "class org.springframework.web.servlet.support.AbstractDispatcherServletInitializer"
2 = {[email protected]} "class org.springframework.web.server.adapter.AbstractReactiveWebInitializer"
3 = {[email protected]} "class org.springframework.web.context.AbstractContextLoaderInitializer"
4 = {[email protected]} "class com.github.binarylei.MyAbstractAnnotationConfigDispatcherServletInitializer"

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

Spring 官方文档注解配置

使用 tomcat7-maven-plugin 插件模拟 Spring Boot。Tomcat 对 Servlet 的支持如下:

Tomcat 6.x 实现 Servert 2.5
Tomcat 7.x 实现 Servert 3.0
Tomcat 8.x 实现 Servert 3.1
Tomcat 9.x 实现 Servert 4.0

(1) WebApplicationInitializer 实现类

public class MyAbstractAnnotationConfigDispatcherServletInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{MyRootConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{MyServletConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/*"};
    }
}

@Configuration
@ComponentScan(basePackages = "com.github.binarylei",
        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})
public class MyServletConfig {
}

@Configuration
@ComponentScan(basePackages = "com.github.binarylei",
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})
public class MyRootConfig {
}

(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>
</dependencies>

<build>
    <plugins>
        <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



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

原文地址:https://www.cnblogs.com/binarylei/p/10203391.html

时间: 2024-08-27 11:39:32

Spring 注解驱动(二)WEB 注解开发的相关文章

spring学习(二)——注解

近期看github上Java项目接触到多种注解,这里对其使用场景做简单的整理 问题: 1. 为什么要用注解?不用注解是否可以实现? 2. 注解的组成? 注解类似一个接口 注解可以定义可指定的属性 3. 如何自定义注解? 4. java spring框架中有哪些已有的注解? 注解 使用场景 备注 @Configuration 类似于xml中<beans>标签   @Bean 类似于xml中<bean>标签 常与@Configuration配合使用  @ComponentScan 可指

跟王老师学注解(二)注解的分类及内建注解

跟王老师学注解(二):注解的分类及内建注解 主讲教师:王少华   QQ群号:483773664 一.注解的分类 在Java中,根据注解的使用方法和用途,可将注解分成3类,分别是 内建注解(也称为基本注解),定义于java.lang包下 元注解(Meta Annotation) 自定义注解 二.内建注解 (一)分类 在JDK5.0及以上的版本的java.lang包下提供了3种标准的注解类型,分别是 @Override: @Deprecated @SuppressWarnings (二)@Overr

从Spring到SpringBoot构建WEB MVC核心配置详解

目录 理解Spring WEB MVC架构的演变 认识Spring WEB MVC 传统时代的Spring WEB MVC 新时代Spring WEB MVC SpringBoot简化WEB MVC开发 自动装配 条件装配 外部化配置 本章源码下载 理解Spring WEB MVC架构的演变 基础Servlet架构 核心架构:前端控制器 Spring WEB MVC架构 认识Spring WEB MVC 传统时代的Spring WEB MVC 怎么讲呢?就是很传统的使用Spring Framew

java web的开发 知识要点

近期闲下来时写的一个有关 java web的开发 的 常用架构 的总结,用于初 学 者或团队新人培训. Java开发初步.ppt SSH  为 struts+spring+hibernate 的一个集成框架,是目前较流行的一种JAVA Web应用程序开源框架 SSI   为 Strtus2.Spring.iBatis java web的开发 知识要点

Spring注解驱动开发(二)--组件注入

一.前言 上一篇我们搭建了一个简单的Spring项目,并简单的使用了 组件注册.这一篇中,我们来详细的讲解组件注入. 二.组件注入 1. @ComponentScan 在上一篇中,我们使用了@Configuration和@Bean实现了组件注入.但是如果需要注入的组件很多的情况下,每个组件都需要通过一个@Bean注解进行注入,这样就会很麻烦.所以Spring提供了@ComponentScan注解. @ComponentScan可以指定需要扫描的包,在这些包下,@Component注解标注的组件都

Spring注解驱动开发(一)--项目搭建

一. 前言 <Spring注解驱动开发>系列文章是基于Spring的4.3.11.RELEASE版本,通过注解的方式进行开发演示. 二. 项目搭建 1.依赖包引用 创建一个maven工程,引入相关的依赖包.我们以依赖最少的原则只引用spring-context和junit包. <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>s

框架 day37 Spring事务管理,整合web,SSH整合,SSH整合注解

1     事务管理 1.1   回顾事务     事务:一组业务操作,要么全部成功,要么全部不成功.     事务特性:ACID 原子性:整体 一致性:数据(完整) 隔离性:并发(多个事务) 持久性:结果     隔离问题:脏读.不可重复读.幻读(虚读)     隔离级别:4个 readuncommitted 读未提交,存在3个问题. readcommitted 读已提交,解决:脏读:存在2个. repeatableread 可重复读,解决:脏读.不可重复读:存在1个 serializ

SSH框架搭建 笔记 (含spring注解驱动)

分类: web 开发2014-04-27 12:33 354人阅读 评论(0) 收藏 举报 框架springinterface注解 好久没有搭建框架了,今天整理下以前的知识,整合下SSH,没想到手生了,一时半会各种异常出来,经过一番挣扎后,终于搞出来了雏形, 下面是我做整合框架的笔记,如果大家开发过程中又遇到的情况,可以参考下 首先是包的结构,(命名不算正规哈~,临时写的仓促了点) 框架是基于JAR包的基础上构建的,所以必须必备的jar包必须先下好, 如图: 没有的可以在本文源代码里下: 搭建框

(转)Spring使用AspectJ进行AOP的开发:注解方式

http://blog.csdn.net/yerenyuan_pku/article/details/69790950 Spring使用AspectJ进行AOP的开发:注解方式 之前我已讲过Spring使用AspectJ通过配置文件的方式来进行AOP的开发,现在就来讲怎样使用注解方式进行AOP的开发. 创建一个Web项目, 引入相关的jar包.所要导入的jar包如下:  引入Spring的配置文件.主要引入AOP的约束: <?xml version="1.0" encoding=