227 lines
10 KiB
Markdown
227 lines
10 KiB
Markdown
|
---
|
|||
|
title: 使用 Maven 创建 Spring MVC 项目
|
|||
|
date: 2020-11-11 15:52:52
|
|||
|
tags:
|
|||
|
- Spring
|
|||
|
- Spring MVC
|
|||
|
- Maven
|
|||
|
categories:
|
|||
|
- Spring
|
|||
|
---
|
|||
|
> Maven 可以用来创建 Java 项目,并管理依赖,创建出来的项目不依赖于特定的 IDE,可以用 Eclipse、IDEA 社区版、IDEA 旗舰版,甚至 VSCode 来开发。_(具体 VSCode 怎么配置 Java 开发环境,这里不再赘述)_
|
|||
|
|
|||
|
> Maven 创建项目时,需要从国外的服务器上下载项目的依赖、插件等,速度会很慢,甚至导致创建项目失败,具体如何配置,请参考我的另一篇博客 [Maven 的相关配置](http://zhouxy.xyz/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/Maven-%E7%9A%84%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE/)。
|
|||
|
|
|||
|
## 一、创建 Java Web 项目
|
|||
|
|
|||
|
### 1. 使用 maven 创建 Java Web 项目
|
|||
|
|
|||
|
启动开发环境,用 Maven 创建项目,从原型中选择“maven-archetype-webapp”,再依次指定 groupId、artifactId 等信息,不同的 IDE 创建 Maven 项目的过程略有不同,但大同小异。
|
|||
|
|
|||
|
### 2. 完善目录结构
|
|||
|
|
|||
|
在 `main` 文件夹中创建 `java` 和 `resources` 两个文件夹;在 `src` 文件夹中创建 `test` 文件夹,并中其中也创建 `java` 和 `resources` 两个文件夹。
|
|||
|
|
|||
|
- ${basedir}/src/main/java 文件夹中创建 Java 包和类;
|
|||
|
- ${basedir}/src/main/resources 文件夹中存放静态文件;
|
|||
|
- ${basedir}/src/test/java 文件夹中创建项目的测试类,比如说 Junit 代码;
|
|||
|
- ${basedir}/src/test/resources 存放测试用的资源。
|
|||
|
|
|||
|
> 在 IDEA 中新建目录时,会有几个提示,因为 IDEA 通过 pom.xml 文件知道这是个 maven 项目,猜测并帮助你创建标准的 maven 项目骨架。这时候按住 shift 键,并按住下方向键,可将其全部选中,再按回车,即可一次性创建好所有文件夹并标记好,这样就不用一个一个创建并标记了。在 VSCode 中,并不会对项目中的文件夹进行标记(VSCode 的一些图标可能会根据文件名进行猜测),所以一个一个创建文件夹就完事了。
|
|||
|
|
|||
|
初始的项目路径如下:
|
|||
|
![初始项目结构](http://zhouxy.xyz/img/163635_48fc6498_6543055.png)
|
|||
|
我们需要完善其目录结构:
|
|||
|
![完善后的目录结构](http://zhouxy.xyz/img/164009_81ccdf56_6543055.png)
|
|||
|
|
|||
|
### 3. 添加 Servlet 和 JSP 的依赖包
|
|||
|
在 pom.xml 文件中的 `dependencies` 标签中添加 Servlet 和 JSP 的依赖:
|
|||
|
```xml
|
|||
|
<!-- Servlet -->
|
|||
|
<dependency>
|
|||
|
<groupId>javax.servlet</groupId>
|
|||
|
<artifactId>javax.servlet-api</artifactId>
|
|||
|
<version>4.0.1</version>
|
|||
|
</dependency>
|
|||
|
|
|||
|
<!-- JSP 和 标签库(用不着的话就不用导) -->
|
|||
|
<dependency>
|
|||
|
<groupId>javax.servlet.jsp</groupId>
|
|||
|
<artifactId>javax.servlet.jsp-api</artifactId>
|
|||
|
<version>2.3.3</version>
|
|||
|
</dependency>
|
|||
|
<dependency>
|
|||
|
<groupId>jstl</groupId>
|
|||
|
<artifactId>jstl</artifactId>
|
|||
|
<version>1.2</version>
|
|||
|
</dependency>
|
|||
|
```
|
|||
|
这样,一个 Java Web 项目就创建好了。
|
|||
|
|
|||
|
|
|||
|
## 二、配置 Spring MVC
|
|||
|
|
|||
|
### 1. 导入 Spring、Spring MVC 的依赖
|
|||
|
|
|||
|
在 pom.xml 文件中的 `dependencies` 标签中添加如下依赖:
|
|||
|
```xml
|
|||
|
<dependency>
|
|||
|
<groupId>org.springframework</groupId>
|
|||
|
<artifactId>spring-webmvc</artifactId>
|
|||
|
<version>5.2.8.RELEASE</version>
|
|||
|
</dependency>
|
|||
|
```
|
|||
|
> 导入 spring-webmvc 好像就会自动导入 spring-aop、spring-beans、spring-context、spring-core、spring-expression、spring-web 这些个依赖。
|
|||
|
|
|||
|
### 2. 配置并启用 Spring MVC
|
|||
|
|
|||
|
以前(包括现在很多人)配置 Spring MVC 都是通过 web.xml 配置的,随着 Java 和 Spring 的发展,现在完全可以不使用 xml 配置并启用 Spring MVC。
|
|||
|
|
|||
|
下面的配置适用于 Spring 3.2 及以上版本(我写本文时,Spring 的版本已经是 5.2.9 了),且 Servlet 容器支持 Servlet 3.0(2009 年 12 月发布)。所以,你的开发环境大概率支持以下配置方法。
|
|||
|
|
|||
|
#### 2.1.1 创建 RootConfig 配置类
|
|||
|
|
|||
|
**RootConfig 类将用于非 web 部分的配置。** *本示例中重在与 Web 相关的配置,所以 `RootConfig` 相对简单,实际项目中将会有很多非 Web 的配置来充实完善 RootConfig。*
|
|||
|
|
|||
|
```java
|
|||
|
package xyz.zhouxy.chapter01.config;
|
|||
|
|
|||
|
import org.springframework.context.annotation.ComponentScan;
|
|||
|
import org.springframework.context.annotation.Configuration;
|
|||
|
import org.springframework.context.annotation.FilterType;
|
|||
|
import org.springframework.context.annotation.ComponentScan.Filter;
|
|||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|||
|
|
|||
|
@Configuration
|
|||
|
@ComponentScan(basePackages = "xyz.zhouxy.chapter01",
|
|||
|
excludeFilters = {
|
|||
|
@Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)})
|
|||
|
public class RootConfig {
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 2.1.2 创建 WebConfig 配置类
|
|||
|
|
|||
|
WebConfig 将用于 DispatcherServlet 应用程序上下文配置。
|
|||
|
|
|||
|
```java
|
|||
|
package xyz.zhouxy.chapter01.config;
|
|||
|
|
|||
|
import org.springframework.context.annotation.Bean;
|
|||
|
import org.springframework.context.annotation.ComponentScan;
|
|||
|
import org.springframework.context.annotation.Configuration;
|
|||
|
import org.springframework.web.servlet.ViewResolver;
|
|||
|
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
|
|||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||
|
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
|||
|
|
|||
|
@Configuration
|
|||
|
@EnableWebMvc
|
|||
|
@ComponentScan("xyz.zhouxy.chapter01.web")
|
|||
|
public class WebConfig implements WebMvcConfigurer {
|
|||
|
|
|||
|
@Bean
|
|||
|
public ViewResolver viewResolver() {
|
|||
|
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
|
|||
|
resolver.setPrefix("/WEB-INF/views/");
|
|||
|
resolver.setSuffix(".jsp");
|
|||
|
resolver.setExposeContextBeansAsAttributes(true);
|
|||
|
return resolver;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
|||
|
configurer.enable();
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
- `@EnableWebMvc` 注解启动 Spring MVC;
|
|||
|
- `@ComponentScan` 启用组件扫描;所指定的包中的所有带有 `@Controller` 注解的类都会成为 Spring bean。
|
|||
|
- `viewResolver` 方法配置 JSP 视图解析器,将 `InternalResourceViewResolver` 类的实例声明为 bean;
|
|||
|
- 重写的 `configureDefaultServletHandling` 方法,通过调用 `DefaultServletHandlerConfigurer` 的 `enable()`,要求 `DispatcherServlet` 将对静态资源的请求转发到 Servlet 容器中默认的 Servlet 上,而不是使用 `DispatcherServlet` 本身来处理此类请求。
|
|||
|
|
|||
|
|
|||
|
> 《Spring 实战(第4版)》中,WebConfig 是继承自 `WebMvcConfigurerAdapter` 类,但当前的版本,该类已经过时,`WebConfig` 类实现 `WebMvcConfigurer` 接口即可。
|
|||
|
|
|||
|
#### 2.1.3 创建 WebAppInitializer 类
|
|||
|
|
|||
|
当我们创建了 `RootConfig` 和 `WebConfig` 配置类之后,怎么让它们应用于我们的项目呢?答案是通过写一个 `WebAppInitializer`。
|
|||
|
|
|||
|
`WebAppInitializer` 类继承自 `AbstractAnnotationConfigDispatcherServletInitializer`,所以它会自动地配置 `DispatcherServlet` 和 Spring 应用上下文,Spring 应用上下文会位于应用程序的 Servlet 上下文中。
|
|||
|
|
|||
|
```java
|
|||
|
package xyz.zhouxy.chapter01.config;
|
|||
|
|
|||
|
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
|
|||
|
|
|||
|
public class WebAppInitializer
|
|||
|
extends AbstractAnnotationConfigDispatcherServletInitializer {
|
|||
|
|
|||
|
@Override
|
|||
|
protected Class<?>[] getRootConfigClasses() {
|
|||
|
return new Class<?>[]{ RootConfig.class };
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
protected Class<?>[] getServletConfigClasses() {
|
|||
|
return new Class<?>[]{ WebConfig.class };
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
protected String[] getServletMappings() {
|
|||
|
return new String[] { "/" };
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
> **更多细节:**
|
|||
|
> 在 Servlet 3.0 环境中,容器会在类路径中查找 `javax.servlet.ServletContainerInitializer` 接口的实现类,找到的话,就用它来配置 Servlet 容器。Spring 的 `SpringServletContainerInitializer` 类即为该接口的实现类,`SpringServletContainerInitializer` 又会查找实现 `WebApplicationInitializer` 的类并将配置的任务交给它们来完成。
|
|||
|
>
|
|||
|
> Spring 3.2 中引入了一个便利的 `WebApplicationInitializer` 基础实现,也就是 `AbstractAnnotationConfigDispatcherServletInitializer`。
|
|||
|
>
|
|||
|
> 因为我们的 `WebAppInitializer` 继承自 `AbstractAnnotationConfigDispatcherServletInitializer`(同时也就实现了 `WebApplicationInitializer` 接口),因此当部署到 Servlet 3.0 容器中的时候,容器会自动发现它,并用它来配置 Servlet 上下文。
|
|||
|
|
|||
|
|
|||
|
## 三、使用 Spring MVC
|
|||
|
|
|||
|
前面我们已经配置好了 Spring MVC,接下来我们编写一个 Controller 来测试一下吧。
|
|||
|
|
|||
|
### 1. 创建页面
|
|||
|
在 ${basedir}/src/main/webapp/WEB-INF/ 文件夹中新建一个 `views` 文件夹,再在 `views` 文件夹中新建 `test.jsp` 文件:
|
|||
|
```html
|
|||
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
|||
|
pageEncoding="UTF-8"%>
|
|||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
|||
|
|
|||
|
<html>
|
|||
|
<head>
|
|||
|
<title>Test</title>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<h1>Test Page</h1>
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
```
|
|||
|
### 2. 创建 TestController
|
|||
|
```java
|
|||
|
package xyz.zhouxy.chapter01.web;
|
|||
|
|
|||
|
import org.springframework.stereotype.Controller;
|
|||
|
import org.springframework.web.bind.annotation.GetMapping;
|
|||
|
|
|||
|
@Controller
|
|||
|
public class TestController {
|
|||
|
|
|||
|
@GetMapping("/test")
|
|||
|
public String toTestPage() {
|
|||
|
return "test";
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
### 3. 部署项目
|
|||
|
将项目部署到 Tomcat,应用上下文为 `chapter01`。
|
|||
|
> 不同 IDE 配置 Tomcat 部署项目具体细节找时间再写吧。
|
|||
|
|
|||
|
在浏览器输入 http://localhost:8080/chapter01/test ,由于上面的映射,`toTestPage()` 方法将被执行,它返回字符串“test”,被视作视图的名称,由 `WebConfig` 类中配置的视图解析器解析为具体的视图 `/WEB-INF/views/test.jsp`。
|
|||
|
![运行结果](http://zhouxy.xyz/img/233117_0a37d814_6543055.png "屏幕截图.png")
|