工作原理
1.在maven中导入springMVC依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
2.web.xml中配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 置顶注册编码过滤器,设置编码之前不能获取任何请求的数据-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置请求体的编码格式-->
<init-param>
<!-- 设置CharacterEncodingFilter中Encoding属性的值-->
<param-name>encoding</param-name>
<!-- 将值改为UTF-8-->
<param-value>UTF-8</param-value>
</init-param>
<!-- 设置响应体的编码格式-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 过滤请求范围-->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 注册put、delete请求过滤器-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置SpringMVC核心控制器,对浏览器发送的请求统一处理-->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置SpringMVC的配置文件的位置和名称-->
<init-param>
<!-- 上下文配置路径-->
<param-name>contextConfigLocation</param-name>
<!-- 类路径-->
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<!-- 设置核心控制器初始化时间
当值为0或者大于0时,表示容器在应用(服务器)启动时就加载并初始化
当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--启动spring容器-->
<!--指定spring配置文件的位置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
springMVC.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描组件
context命名空间:
扫描多个包用逗号隔开
-->
<context:component-scan base-package="com.kgc"/>
<!--配置Thymeleaf视图解析器-->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<!-- 设置视图解析器的优先级-->
<property name="order" value="1"/>
<!-- 解析视图时所用的编码格式-->
<property name="characterEncoding" value="UTF-8"/>
<!-- 模板-->
<property name="templateEngine">
<!-- 内部bean为模板属性赋值-->
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 解析视图的策略-->
<!--视图前缀-->
<property name="prefix" value="/templates/"/>
<!--视图后缀-->
<property name="suffix" value=".html"/>
<!-- 模板中的模型-->
<property name="templateMode" value="HTML5"/>
<!-- 页面的编码格式-->
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!-- 视图控制器:view-controller
path:设置处理请求的地址
view-name:设置请求地址对应的视图名称-->
<!-- <mvc:view-controller path="/file" view-name="file"/>-->
<mvc:view-controller path="/upFile" view-name="upFile"/>
<!-- 当SpringMVC中设置任何一个view-controller时,
其他控制器中的请求映射将全部失效,此时需要开启mvc注解驱动-->
<!-- 开启mvc的注解驱动-->
<mvc:annotation-driven/>
<!-- 静态页面放行-->
<mvc:default-servlet-handler/>
<!-- 配置文件上传解析器,将上传的文件封装为multipartFile-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件上传的默认编码格式-->
<property name="defaultEncoding" value="utf-8"/>
<!-- 单个文件大小限制(byte)-->
<property name="maxUploadSizePerFile" value="#{10*1024*1024}"/>
<!-- 整个请求大小限制(byte)-->
<property name="maxUploadSize" value="#{100*1024*1024}"/>
</bean>
<!--配置拦截器-->
<!-- <mvc:interceptors>-->
<!-- <!–配置拦截器,多个拦截器时,顺序执行–>-->
<!-- <mvc:interceptor>-->
<!-- <!–要拦截的具体的方法–>-->
<!-- <mvc:mapping path="/**"/>-->
<!-- <!–不去拦截的方法–>-->
<!-- <mvc:exclude-mapping path="/"/>-->
<!-- <!–配置拦截器对象–>-->
<!-- <bean class="com.kgc.interceptors.FirstInterceptor"/>-->
<!-- </mvc:interceptor>-->
<!-- </mvc:interceptors>-->
<!-- 配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
key里是异常的全类名,value为视图名称视图解析器会解析
出现该异常时会自动跳转到设置的视图页面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!-- value的值为存储在共享域中的键,值为发生异常的异常信息-->
<property name="exceptionAttribute" value="ex"/>
</bean>
</beans>
- 浏览器发送请求,若请求地址符合前端控制器的url-pattern(web.xml中的url-pattern标签),该请求就会被前端控制器DispatcherServlet处理。
- 前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中
- @RequestMapping注解的value属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法。
- 处理请求的方法需要返回一个字符串类型的视图名称
- 该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径
- 通过Thymeleaf对视图进行渲染,最终转发到视图所对应页面
@RequestMapping注解
属性:
- value:通过请求地址来匹配请求 (/地址)
- method:通过请求方式来匹配请求 (get/post)
- params:通过请求参数来匹配请求
- headers:通过请求头信息来匹配请求
派生注解
1、对于处理指定请求方式的控制器方法,SpringMVC中提供 了@RequestMapping的派生注解
- 处理get请求的映射—>@GetMapping
- 处理post请求的映射—>@PostMapping
- 处理put请求的映射—>@PutMapping
- 处理delete请求的映射—>@DeleteMapping
2、常用的请求方式有get, post, put, delete
但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符串(put或delete),则按照默认的请求方式get处理
若要发送put和delete请求,则需要通过spring提供的过滤器HiddenHttpMethodFilter
SpringMVC支持ant风格的路径
value=””中可以这样写路径
- ? :表示任意的单个字符
- *:表示任意的0个或多个字符
- **:表示任意的一层或多层目录
@RequestParam注解
将请求参数和控制器方法形参创建映射关系
请求参数注解:
- value:和请求参数名一致
- name:和请求参数名一致
- required:自动装配 默认true,当参数值为null会400错误
- defaultValue:当请求参数为null或者空字符串时
@RequestHeader注解
将请求头信息和控制器方法形参创建映射关系
属性和@RequestParam注解一致@CookieValue注解
将cookie数据和控制器方法形参创建映射关系注册过滤器处理中文乱码问题
<!-- 注册过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置请求体的编码格式-->
<init-param>
<!-- 设置CharacterEncodingFilter中Encoding属性的值-->
<param-name>encoding</param-name>
<!-- 将值改为UTF-8-->
<param-value>UTF-8</param-value>
</init-param>
<!-- 设置响应体的编码格式-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 过滤请求范围-->
<url-pattern>/*</url-pattern>
</filter-mapping>
CharacterEncodingFilter类中三个属性和一个方法
```java @Nullable //编码格式 private String encoding; //请求编码处理 private boolean forceRequestEncoding; //响应编码处理 private boolean forceResponseEncoding; //默认是不开启处理 public CharacterEncodingFilter() {
}this.forceRequestEncoding = false;
this.forceResponseEncoding = false;
//过滤器执行方法
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//先看是否设置了编码格式,没设置默认为null
String encoding = this.getEncoding();
if (encoding != null) {
//看是否开启响应/请求编码格式处理
if (this.isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
if (this.isForceResponseEncoding()) {
response.setCharacterEncoding(encoding);
}
}
filterChain.doFilter(request, response);
}
<a name="uV0XB"></a>
## session 的钝化和活化
假设我们在淘宝中用户过多的时候,虽然 session 没有下限,但 session 的数量就会不断增多。之后就会导致内存无法承受,此时就会有一些 session 长时间都没有活动。服务器启动时就会将这些很久没有活动的 session 放到硬盘上,让内存给空出来。就会使得很多的session被保存到硬盘上以此来空出内存。而即便之后需要再次访问 session,它就会再次从硬盘中将 session给放到内存中来使用。这样用户就不会感觉到自己掉线了。这个过程就是 session 的钝化和活化。<br />而钝化和活化最终都是把 session 保存到硬盘中,再从硬盘中回到内存中。<br />但是他们和session序列化、反序列化发生的时间点不一样。session序列化反序列化是关闭和启动服务器,session钝化和活化是没有关闭和启动服务器就完成了
<a name="smy2X"></a>
## ModelAndView对象
model:用于向请求域共享数据<br />view:用于设置视图,实现页面跳转<br />ModelAndView mav=new ModerlAndView();<br />mav.addObjet(String name,Object value)<br />mav.setViewName(String name)
<a name="f2cuC"></a>
## 重定向和转发
转发:forward:/请求名称 创建internalResourceView视图<br />重定向:redirect:/请求名称 创建RedirectView视图<br />(不支持视图解析器)
<a name="xCgoA"></a>
## RESTFul
[<br />](https://blog.csdn.net/qq_39671996/article/details/124352227)![image.png](https://cdn.nlark.com/yuque/0/2022/png/28829722/1654971693558-c4b745f8-80a2-47f9-890d-65917b306d5f.png#clientId=ue6e2d889-171c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=475&id=u81517481&margin=%5Bobject%20Object%5D&name=image.png&originHeight=950&originWidth=1583&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1021082&status=done&style=none&taskId=u4c52b20c-de99-4970-ac3d-ff0968a1dfb&title=&width=791.5)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/28829722/1654875986442-55426c8a-95ca-45d2-8543-d37d48dd5b38.png#clientId=ue15e1266-d654-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=173&id=CDM1A&margin=%5Bobject%20Object%5D&name=image.png&originHeight=346&originWidth=822&originalType=binary&ratio=1&rotation=0&showTitle=false&size=110120&status=done&style=none&taskId=uc0f3e01a-6ba2-43b3-86d1-e00e79fc3a1&title=&width=411)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/28829722/1654972652286-721d3e3e-751c-43a3-be3f-3fe601395b60.png#clientId=ue6e2d889-171c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=404&id=u39973f2f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=808&originWidth=1584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=697543&status=done&style=none&taskId=ud9ddeab9-9c1b-4893-a65a-60d695c81e9&title=&width=792)
<a name="SNTc9"></a>
### 日期格式化
@DateTimeFormat (pattern = "yyyy-MM-dd" )<br />在实体类date属性上加<br />@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")//主要是限制前台的时间格式<br />@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")//主要是控制后台到前台的时间格式
<a name="Q7Go1"></a>
## HttpMessageConverter报文信息转换器
@RequestBody RequestEntity<br />@ResponseBody ResponseEntity<br />在控制器方法上加@ResponseBody 注解后返回值为响应体<br />与Response.getWriter().print("响应体")效果相同
---
**ResponseEntity**<br />ResponseEntity的优先级高于@ResponseBody。在不是ResponseEntity的情况下才去检查有没有@ResponseBody注解。如果响应类型是ResponseEntity可以不写@ResponseBody注解,写了也没有关系。简单的说
1. @ResponseBody可以直接返回Json结果,
1. @ResponseEntity不仅可以返回json结果,还可以定义返回的HttpHeaders和HttpStatus
<a name="xPMtn"></a>
### 解决响应体为json格式
导入依赖<br />_<!-- jackson依赖处理json格式--><br /> _<**dependency**><br /> <**groupId**>com.fasterxml.jackson.core</**groupId**><br /> <**artifactId**>jackson-databind</**artifactId**><br /> <**version**>2.12.1</**version**><br /> </**dependency**><br />在springmvc配置文件中开启<br />_<!-- 开启mvc的注解驱动--><br />_<**mvc:annotation-driven**/><br />json的两种格式对象和数组
<a name="ppNIJ"></a>
### @RestController派生注解
@RestController注解是SpringMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解
<a name="C5Y24"></a>
### ResponseEntity实现文件下载
```java
@RequestMapping("/xiazai/{filename}")
@ResponseBody
public ResponseEntity<byte[]> testResponseEntity(@PathVariable("filename") String filename, HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/photo/"+filename);
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename="+filename);
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
上传功能
<dependencies>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<form action="/addfile" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="photo"><br/>
<input type="submit" value="上传">
</form>
@RequestMapping("/addfile")
public String addfile(MultipartFile photo,HttpSession session)throws IOException{
//获取上传的文件名
String filename = photo.getOriginalFilename();
//截取文件后缀名
String hzm=filename.substring(filename.lastIndexOf("."));
String uuid= UUID.randomUUID().toString();
//根据uuid生成的唯一文件名
String finalName=uuid+hzm;
//将文件名保存到数据库中
fileServce.addFile(new File(null,finalName));
//通过ServletContext获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
//查看服务器中是否有photo目录
java.io.File file = new java.io.File(photoPath);
if (!file.exists()){
//若不存在,则创建目录
file.mkdir();
}
//路径加文件名
String finalPath =photoPath+ java.io.File.separator+finalName;
//上传文件
photo.transferTo(new java.io.File(finalPath));
//重定向页面
return "redirect:/file";
}
删除文件
@RequestMapping("/deleteFile/{fileid}")
public String deleteFile(@PathVariable("fileid")Integer fileid,HttpSession session){
//获取删除的文件id和名称
File fileById = fileServce.getFileById(fileid);
String filename = fileById.getFilename();
//通过ServletContext获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String realPath = servletContext.getRealPath("photo");
//拼接photo目录路径和文件名
String finalName=realPath+"/"+filename;
//创建io对象,删除文件
java.io.File file=new java.io.File(finalName);
boolean delete = file.delete();
//将数据库中的文件也删除
fileServce.deleteFile(fileid);
//重定向页面
return "redirect:/file";
}
拦截器
在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用
过滤器和拦截器的区别?
过滤器(filter):
1) filter属于Servlet技术,只要是web工程都可以使用
2) filter主要对所有请求过滤
3) filter的执行时机早于Interceptor
拦截器(interceptor)
1) interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
2) interceptor通常对处理器Controller进行拦截
3) interceptor只能拦截dispatcherServlet处理的请求
应用场景
1)日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2)权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
3)性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4)通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。
拦截器方法说明
preHandle方法
作用:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。<br /> 执行时机:在处理器方法执行前执行 <br /> 方法参数:<br /> 1)request请求对象<br /> 2)response响应对象<br /> 3)handler拦截到的方法处理
postHandle方法
作用:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改<br /> 执行时机:在处理器的方法执行后,视图渲染之前<br /> 方法参数:<br /> 1)request请求对象<br /> 2)response响应对象<br /> 3)handler拦截到的处理器方法<br /> 4)ModelAndView处理器方法返回的模型和视图对象,可以在方法中修改模型和视图
afterCompletion方法
作用:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象<br /> 执行时机:视图渲染完成后(整个流程结束之后)<br /> 方法参数:<br /> 1)request请求参数<br /> 2)response响应对象<br /> 3)handler拦截到的处理器方法<br /> 4)ex异常对象
在SpringMVC中配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器,多个拦截器时,顺序执行-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/**"/>
<!--不去拦截的方法-->
<mvc:exclude-mapping path="/"/>
<!--配置拦截器对象-->
<bean class="com.kgc.interceptors.FirstInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
在SpringMVC中配置异常处理器
<!-- 配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
key里是异常的全类名,value为视图名称视图解析器会解析
出现该异常时会自动跳转到设置的视图页面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!-- value的值为存储在共享域中的键,值为发生异常的异常信息-->
<property name="exceptionAttribute" value="ex"/>
</bean>
基于注释配置异常处理器
@ControllerAdvice 将当前类标识为异常处理组件
@ExceptionHandler 设置所标识方法处理的异常(异常名称.class)
//将当前类标识为异常处理组件
@ControllerAdvice
public class ExceptionTest {
//设置所标识方法处理的异常(异常名称.class)
@ExceptionHandler(ArithmeticException.class)
//exception内是异常具体信息
public String ex(Exception exception, Model model){
model.addAttribute("ex",exception);
return "error";
}
}
Spring MVC五大组件及作用
DispatcherServlet
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
HandlerMapping
HandlerMapping 是处理器映射,它的作用是请求派发,负责请求和控制器建立对应的关系。它是由 DispatcherServlet 调用,DispatcherServlet 会从容器中取出所有 HandlerMapping 实例并遍历,让 HandlerMapping 实例根据自己实现类的方式去尝试查找 Handler。也就是说,DispatcherServlet要将一个请求交给哪个特定的Controller,它需要咨询一个Bean,这个Bean的名字为“HandlerMapping”。
Controller
控制器,负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。
ModelAndView
封装数据信息和视图信息的模型。使用ModelAndView类用来存储处理完后的结果数据,以及显示该数据的视图。从名字上看ModelAndView中的Model代表模型,View代表视图,这个名字就很好地解释了该类的作用。业务处理器调用模型层处理完用户请求后,把结果数据存储在该类的model属性中,把要返回的视图信息存储在该类的view属性中,然后让该ModelAndView返回该Spring MVC框架。框架通过调用配置文件中定义的视图解析器,对该对象进行解析,最后把结果数据显示在指定的页面上。
ViewResolver
视图解析器,ViewResolver 的主要作用是把一个逻辑上的视图名称解析为一个真正的视图。
五大组件的关系
DispatcherServlet收到请求后,依据HandlerMapping的配置,调用相应的Controller来处理,Controller将处理结果封装成ModelAndView对象,返回给DispatcherServlet,DispatcherServlet依据ViewResolver的解析,调用相应的视图对象,(如jsp)来生成相应的页面。