Spring MVC项目创建
什么是Spring MVC
Spring MVC是Spring内置的,实现了Web MVC设计模式的框架。
它解决了Web开发过程中很多的问题,例如参数接收、表单验证等。另外它采用松散耦合可插拔组件等结构,具有相对较高的灵活性和扩展性。
Spring MVC官方文档可参考 docs.spring.io。
Spring MVC执行流程
按顺序可分为如下流程
- 用户请求被
DispatcherServlet
进行拦截处理 DispatcherServlet
收到请求调用HandlerMapping
HandlerMapping
找到具体的处理器,生成处理器对象及处理器拦截器,再一起返回给DispatcherServlet
DispatcherServlet
调用HandlerAdapter
HandlerAdapter
经过适配调用具体的处理器- Controller执行完成返回
ModelAndView
对象 HandlerAdapter
将ModelAndView
返回给DispatcherServlet
DispatcherServlet
将ModelAndView
传给ViewReslover
ViewReslover
解析ModelAndView
后返回View(给DispatcherServlet
DispatcherServlet
根据View进行渲染DispatcherServlet
响应View给用户
通过上面流程可知,程序员需要配置DispatcherServlet
,并开发View
和Controller/Handler
。
项目创建
即然如此,我们就来创建一个Spring MVC项目。
打开Eclipse,创建一个Maven项目(想必经过前面学习已经很熟了),项目名称top.cairbin.test7
。
但是需要注意,创建时请勾选下图的Add project(s) to working set
在Select an Archetype
这一步需要注意,我们不再用之前的maven-archetype-quickstart
,而是maven-archetype-webapp
,如下图所示
创建完成后项目目录结构大概如下
我们还需要引入Spring MVC的依赖包以及Servlet,这你很清楚应该在pom.xml
里配置
xml
<!-- 添加servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
<version>3.1.0</version>
</dependency>
<!-- 添加spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
最终效果看起来是这样
xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>top.cairbin</groupId>
<artifactId>test7</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>test7 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- 添加servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
<version>3.1.0</version>
</dependency>
<!-- 添加spring依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
</dependencies>
<build>
<finalName>test7</finalName>
</build>
</project>
相比于以往的项目,你会发现webapp
已经为我们创建了一个resources资源文件夹,并且src/main
下多了一个webapp
目录。webapp
它一般存放前端相关的文件。
而webapp
目录下有一个WEB-INF
,里面有一个默认生成的web.xml
配置文件。还记得我们刚才提到的Spring MVC执行流程吗,用户请求会被DispatcherServlet
拦截,它叫前端控制器,而这个XML文件就是用来对它进行设置的。
我们对web.xml
进行修改
xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<!-- 配置前端过滤器 -->
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!-- 初始化时加载配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springCtx.xml</param-value>
</init-param>
<!-- 表示容器在启动时立即加载Servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
注意<param-value>classpath:springCtx.xml</param-value>
这一段引入了一个文件,是用来配置Controller映射信息的。
我们再来看看,webapp
下还有一个index.jsp
文件,它正是你的前端代码文件,它的内容如下
jsp
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
你可能对此表示疑惑,这不就是一个HTML文件,现实一个标题,标题内容为Hello World!
吗。没错,但是对于传统的HTML来讲页面是静态的,而我们的JSP文件则能动态获取后端一些内容。
有了View来实现USL前台还不够,我们还要实现USL后台,接下来我们在src/main/java
下创建包top.cairbin.test7.controller
,并在这个包下创建控制器类TestController
java
package top.cairbin.test7.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class TestController implements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
// 创建ModelAndView对象
ModelAndView mav = new ModelAndView();
// 向模型对象中添加数据
mav.addObject("message", "Hello Spring");
// 设置逻辑视图名
mav.setViewName("/WEB-INF/views/hello.jsp");
// 返回ModelAndView对象
return mav;
}
}
还记得刚才说的<param-value>classpath:springCtx.xml</param-value>
吗,我们创建了控制器,还要告诉Spring MVC控制器与View的映射关系。
springCtx.xml
这个文件并不存在我们项目中,需要手动添加。在resources资源文件夹里创建它。
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置处理器Handle,映射"/hello"请求 -->
<bean name="/hello"
class="top.cairbin.test7.controller.TestController" />
<!-- 处理器映射器,将处理器Handle的name作为url进行查找 -->
<bean class=
"org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- 处理器适配器,配置对处理器中handleRequest()方法的调用-->
<bean class=
"org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 视图解析器 -->
<bean class=
"org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
</beans>
请务必注意<bean name="/hello" class="top.cairbin.test7.controller.TestController" />
这一段的包名与你控制器一致。它告诉Spring MVC,将这个控制器映射到/hello
路径上去,一会你就能在浏览器通过http://ip:port/项目名/hello
的形式去访问它。
在WEB-INF
里创建views
文件夹,请注意是WEB-INF
下创建。
并在这个viewsview
文件夹里新建jsp文件hello.jsp
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello SpringMvc</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
我们在这里使用${...}
的形式来使用后端提供的接口,以此获取后端返回的对象。
那么问题来了,我们这个项目该怎么运行呢?显然对于Web项目我们需要Http服务器。
还记得我们在配置环境的时候安装的Tomcat9吗,现在终于要到了使用它的时候了!
另外,我们注意之前编写的TestController
这个控制器,它需要导入的包中可能有两个报错。
java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
如果出现这种情况,我们右键这个项目,打开属性
找到Java Build Path
选项的Libraries
选项卡,点击Add Library...
选择Server Runtime
选项,然后下一步
选择之前配置好的服务器(就是在环境配置那篇文章里的)
保存并退出。
接下来我们尝试运行它,与以往不同的是,我们需要Run As里面的Run on server
如果你第一次这样做,会弹出个窗口
选择Apache里对应的服务器,我这里是Tomcat9.0
然后点击完成。很显然,你的浏览器已经打开了,说明你的项目跑成功了。并且在Eclipse的Package Explorer中多了个Servers文件夹。
我们在浏览器访问的是index.jsp
所渲染的页面
在地址栏输入http://localhost:8080/test7/hello
访问控制器和hello.jsp
所渲染的页面
问题
在这一节其实有很多坑,一是Tomcat版本在10.0以上的话,包名变化问题。
另外如果当初配置环境的时候,Eclipse没选Web选项,这里有些配置是没有的。
上面这些问题请参考环境配置和此教程的问题模块。
如果你项目菜单里的Run as
没有Run on server
选项的话需要如下操作
打开项目属性
搜索project facets
,勾选Dynamic Web Module
选项
保存并退出。
接下来如果操作不当的话可能导致Servers
文件夹下配置文件里有多个context,这时候需要打开server.xml
进行就该
找到如下片段<Context>
标签,把重复的删除