专栏首页小灰灰Spring MVC之基于java config无xml配置的web应用构建

Spring MVC之基于java config无xml配置的web应用构建

I. Web构建

1. 项目依赖

对于依赖这一块,和前面一样,不同的在于java config 取代 xml

<artifactId>200-mvc-annotation</artifactId>
<packaging>war</packaging>

<properties>
    <spring.version>5.1.5.RELEASE</spring.version>
</properties>

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.eclipse.jetty.aggregate</groupId>
        <artifactId>jetty-all</artifactId>
        <version>9.2.19.v20160908</version>
    </dependency>
</dependencies>

<build>
    <finalName>web-mvc</finalName>
    <plugins>
        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>9.4.12.RC2</version>
            <configuration>
                <httpConnector>
                    <port>8080</port>
                </httpConnector>
            </configuration>
        </plugin>
    </plugins>
</build>

细心的童鞋会看到,依赖中多了一个jetty-all,后面测试篇幅会说到用法

2. 项目结构

第二节依然放上项目结构,在这里把xml的结构也截进来了,对于我们的示例demo而言,最大的区别就是没有了webapp,更没有webapp下面的几个xml配置文件

3. 配置设定

现在没有了配置文件,我们的配置还是得有,不然web容器(如tomcat)怎么找到DispatchServlet呢

a. DispatchServlet 声明

同样我们需要干的第一件事情及时声明DispatchServlet,并设置它的应用上下文;可以怎么用呢?从官方找到教程

{% blockquote @SpringWebMvc教程 https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet %}

The DispatcherServlet, as any Servlet, needs to be declared and mapped according to the Servlet specification by using Java configuration or in web.xml. In turn, the DispatcherServlet uses Spring configuration to discover the delegate components it needs for request mapping, view resolution, exception handling

{% endblockquote %}

上面的解释,就是说下面的代码和web.xml的效果是一样一样的

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {
        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("mvc-dispatcher", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/*");
    }
}

当然直接实现接口的方式有点粗暴,但是好理解,上面的代码和我们前面的web.xml效果一样,创建了一个DispatchServlet, 并且绑定了url命中规则;设置了应用上下文AnnotationConfigWebApplicationContext

这个上下文,和我们前面的配置文件mvc-dispatcher-servlet有点像了;如果有兴趣看到项目源码的同学,会发现用的不是上面这个方式,而是及基础接口AbstractDispatcherServletInitializer

public class MyWebApplicationInitializer extends AbstractDispatcherServletInitializer {
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        //        applicationContext.setConfigLocation("com.git.hui.spring");
        applicationContext.register(RootConfig.class);
        applicationContext.register(WebConfig.class);
        return applicationContext;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/*"};
    }
    
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{new HiddenHttpMethodFilter(), new CharacterEncodingFilter()};
    }
}

看到上面这段代码,这个感觉就和xml的方式更像了,比如Servlet应用上下文和根应用上下文

说明

上面代码中增加的Filter先无视,后续会有专文讲什么是Filter以及Filter可以怎么用

b. java config

前面定义了DispatchServlet,接下来对比web.xml就是需要配置扫描并注册bean了,本文基于JavaConfig的方式,则主要是借助 @Configuration 注解来声明配置类(这个可以等同于一个xml文件)

前面的代码也可以看到,上下文中注册了两个Config类

RootConfig定义如下,注意下注解@ComponentScan,这个等同于<context:component-sca/>,指定了扫描并注册激活的bean的包路径

@Configuration
@ComponentScan(value = "com.git.hui.spring")
public class RootConfig {
}

另外一个WebConfig的作用则主要在于开启WebMVC

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
}

4. 实例代码

实例和上一篇一样,一个普通的Server Bean和一个Controller

@Component
public class PrintServer {
    public void print() {
        System.out.println(System.currentTimeMillis());
    }
}

一个提供rest服务的HelloRest

@RestController
public class HelloRest {
    @Autowired
    private PrintServer printServer;

    @GetMapping(path = "hello", produces="text/html;charset=UTF-8")
    public String sayHello(HttpServletRequest request) {
        printServer.print();
        return "hello, " + request.getParameter("name");
    }


    @GetMapping({"/", ""})
    public String index() {
        return UUID.randomUUID().toString();
    }
}

5. 测试

测试依然可以和前面一样,使用jetty来启动,此外,介绍另外一种测试方式,也是jetty,但是不同的是我们直接写main方法来启动服务

public class SpringApplication {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        ServletContextHandler handler = new ServletContextHandler();

        // 服务器根目录,类似于tomcat部署的项目。 完整的访问路径为ip:port/contextPath/realRequestMapping
        //ip:port/项目路径/api请求路径
        handler.setContextPath("/");

        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.register(WebConfig.class);
        applicationContext.register(RootConfig.class);

        //相当于web.xml中配置的ContextLoaderListener
        handler.addEventListener(new ContextLoaderListener(applicationContext));

        //springmvc拦截规则 相当于web.xml中配置的DispatcherServlet
        handler.addServlet(new ServletHolder(new DispatcherServlet(applicationContext)), "/*");

        server.setHandler(handler);
        server.start();
        server.join();
    }
}

测试示意图如下

6. 小结

简单对比下xml的方式,会发现java config方式会清爽很多,不需要多个xml配置文件,维持几个配置类,加几个注解即可;当然再后面的SpringBoot就更简单了,几个注解了事,连上面的两个Config文件, ServletConfig都可以省略掉

另外一个需要注意的点就是java config的运行方式,在servlet3之后才支持的,也就是说如果用比较老的jetty是起不来的(或者无法正常访问web服务)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SpringBoot+Mysql 无法保存emoj表情?

    尤记得很久以前,想存 emoj 表情到 mysql 中,需要额外的将 emoj 表情转码之后保存,每次读取时,再解码还原成一下;每次这种 sb 的操作,真心感觉...

    一灰灰blog
  • SpringBoot系列教程JPA之基础环境搭建

    JPA(Java Persistence API)Java持久化API,是 Java 持久化的标准规范,Hibernate是持久化规范的技术实现,而Spring...

    一灰灰blog
  • zxing 二维码大白边一步一步修复指南

    二维码边距修复 使用zxing生成二维码时, 某些场景下,即便指定 padding 参数为0,依然有很大的白边,本篇博文主要分析产生这个的原因,以及如何修复这...

    一灰灰blog
  • Spring依赖配置详解

    说故事的五公子
  • 架构师之路----一步步搭建日志监控系统(Spring+SpringMVC+Redis+ELK)

    原文地址 https://my.oschina.net/u/1000241/blog/844651 ? 前言 对于一个优秀的软件架构而言,软件初期的技术选型,开...

    春哥大魔王
  • 实战spring自定义属性(schema):快速体验

    在开发dubbo服务的时候,我们会在xml中做以下类似的配置: <dubbo:application name="dubbo_service_provider"...

    程序员欣宸
  • maven依赖的版本管理

    在一个项目中,这样做的必要性不大,这种机制一般用于maven项目继承,子项目可以直接使用简化的依赖配置,从而确保和父项目版本一致。

    pollyduan
  • ssm项目pom.xml必导入坐标

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    多凡
  • Spring整合Mybatis(IDEA版)

    该文主要教大家如何整合spring和mybatis,整合完成效果,可以从数据库中查询出学生信息:

    说故事的五公子
  • SSM整合所需的maven配置文件

    说故事的五公子

扫码关注云+社区

领取腾讯云代金券