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

简介: 前一篇博文讲了SpringMVC+web.xml的方式创建web应用,用过SpringBoot的童鞋都知道,早就没有xml什么事情了,其实Spring 3+, Servlet 3+的版本,就已经支持java config,不用再写xml;本篇将介绍下,如何利用java config取代xml配置

前一篇博文讲了SpringMVC+web.xml的方式创建web应用,用过SpringBoot的童鞋都知道,早就没有xml什么事情了,其实Spring 3+, Servlet 3+的版本,就已经支持java config,不用再写xml;本篇将介绍下,如何利用java config取代xml配置


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配置文件


image.png


3. 配置设定


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


a. DispatchServlet 声明


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


{% blockquote @SpringWebMvc教程 docs.spring.io/spring/docs… %}

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();
    }
}
复制代码


测试示意图如下

image.png


6. 小结


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


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




相关文章
|
6天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
23天前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
37 1
|
15天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
8天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
20 3
|
18天前
|
SQL 监控 Java
技术前沿:Java连接池技术的最新发展与应用
本文探讨了Java连接池技术的最新发展与应用,包括高性能与低延迟、智能化管理和监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,为开发者提供了一份详尽的技术指南。
28 7
|
16天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
30 3
|
16天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
33 2
|
17天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
10 1
|
21天前
|
移动开发 前端开发 JavaScript
java家政系统成品源码的关键特点和技术应用
家政系统成品源码是已开发完成的家政服务管理软件,支持用户注册、登录、管理个人资料,家政人员信息管理,服务项目分类,订单与预约管理,支付集成,评价与反馈,地图定位等功能。适用于各种规模的家政服务公司,采用uniapp、SpringBoot、MySQL等技术栈,确保高效管理和优质用户体验。
|
21天前
|
SQL 监控 Java
Java性能优化:提升应用效率与响应速度的全面指南
【10月更文挑战第21】Java性能优化:提升应用效率与响应速度的全面指南