视图View
springmvc中常用视图
- InternalResourceView
- 内部资源视图
- 是SpringMVC内置的,专门负责解析JSP模板语法,同时也负责转发功能的实现
- RedirectView
- 重定向视图
- 是SpringMVC内置的,专门负责重定向功能实现
- ThymeleafView
- 第三方,专门负责解析Thymeleaf模板语法的
- 使用时注意
<html lang="en" xmlns:th="http://www.thymeleaf.org">
实现视图机制的核心类和接口
- DispatcherServlet
- 前端控制器
- 负责接收前端的请求
- 根据请求路径找到对应的处理器方法
- 执行处理器方法,并最终返回ModelAndView对象
- ViewResolver接口
- 视图解析器接口
- 将逻辑视图名称转换为物理视图名称(将逻辑名称转换为物理路径),并最终返回一个View接口对象
- View接口
- 视图接口
- 负责将模板语法的字符串转换成html代码,并将html代码响应给浏览器
视图解析流程
下面的各个类|接口都是SpringMVC中源码选取的片段,这些类中方法的执行,反映了底层视图解析的流程
DispatcherServlet类
public class DispatcherServlet extends FrameworkServlet{
// 前端控制器的核心方法,处理请求,返回视图,渲染视图,都是在这个方法中完成
protected void doDispatch(HttpServletRequest request,HttpServletResponse response) throws Exception{
// 根据请求路径调用映射的处理器方法,处理器方法执行结束之后,返回逻辑视图名称
// 返回逻辑视图名称之后,DispatcherServlet会将逻辑视图名称ViewName+Model,将其封装为ModelAndView对象
mv=ha.handle(processedRequest,response,mappedHandler.getHandler());
// 这行代码作用是处理视图
processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);
}
private void processDispatchResult(
HttpServletRequest request,
HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler,
@Nullable ModelAndView mv,
@Nullable Exception exception)throws Exception{
// 渲染页面(将模板字符串转换成html代码响应到服务器)
render(mv,request,response);
}
protected void render(ModelAndView mv,HttpServletRequest request, HttpServletResponse response) throws Exception{
// 这个方法作用是将逻辑视图名称转换成物理视图名称,并且最终返回视图对象view
View view = resolveViewName(viewName,mv.getModelInternal(),locale,request);
// 真正的将模板字符串转换成HTML代码,并且将HTML代码响应给浏览器(真正渲染)
view.render(mv.getModelInternal(),request,response);
}
protected View resolveViewName(
String viewName,
@Nullable Map<String, Object> model,
Locale locale,
HtpServletRequest request) throws Exception{
// 上述render方法中真正调用执行的方法
ViewResolver viewResolver;//底层会创建一个ThymeleafViewResolver
// ,如果使用Thymeleaf,那么该接口实现类就为ThymeleafView对象
View view = viewResolver.resolveViewName(viewName,locale);
return view;
}
}
ViewResolver接口
public interface ViewResolver{
// 这里只是一个规范了行为的接口,具体的实现类要根据所选择的模板解析器来确定(列如,如果使用Thymeleaf,那么该接口实现类就为ThymeleafViewResolver)
// 该方法是将逻辑视图名称转换成物理视图名称,并且最终返回视图对象View
View resolveViewName(String viewName,Locale locale) throws Exception;
}
View接口
// 该接口负责将模板字符串转换成HTML代码,响应给浏览器
public interface View(){
void render(
@Nullable Map<String, ?> model,
HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
代码流程描述
若在SpringMVC中使用了Thymeleaf作为视图
- 浏览器发送请求给web服务器
- Spring MVC中的DispatcherServlet接收到请求
- DispatcherServlet根据请求路径分发到对应的Controller
- DispatcherServlet调用Controller的方法
- Controller的方法处理业务并返回一个逻辑视图名给DispatcherServlet
- DispatcherServlet调用ThymeleafViewResolver的resolveViewName方法,将逻辑视图名转换为物理视图名,并创建ThymeleafView对象返回给DispatcherServlet
- DispatcherServlet再调用ThymeleafView的render方法,render方法将模板语言转换为HTML代码,响应给浏览器,完成最终渲染
若在SpringMVC中使用了JSP作为视图
- 浏览器发送请求给web服务器
- Spring MVC中的DispatcherServlet接收到请求
- DispatcherServlet根据请求路径分发到对应的Controller
- DispatcherServlet调用Controller的方法
- Controller的方法处理业务并返回一个逻辑视图名给DispatcherServlet
- DispatcherServlet调用InternalResourceViewResolver的resolveViewName方法,将逻辑视图名转换为物理视图名,并创建InternalResourceView对象返回给DispatcherServlet
- DispatcherServlet再调用InternalResourceView的render方法,render方法将模板语言转换为HTML代码,响应给浏览器,完成最终渲染。
转发与重定向
转发和重定向的区别
- 转发是一次请求,因此浏览器地址栏上的地址不会发生变化。
- 重定向是两次请求,因此浏览器地址栏上地址会发送变化
- 转发的代码实现
request.getRequestDispatcher("/index").forward(request,response)
- 重定向的代码实现
response.sendRedirect("/webapproot/index")
; - 转发是服务器内部资源跳转,由服务器来控制,不可实现跨域访问
- 重定向可以完成内部资源的跳转也可以完成跨域跳转。
- 转发的方式可以访问WEB-INF目录下受保护的资源
- 重定向相当于浏览器重新发送了一次请求,再浏览器直接发送的请求是无法访问WEB-INF目录下受保护的资源
转发的原理
- 假设发送了/a请求,执行了AServlet
- 在Aservlet中通过
request.getRequestDispatcher("/b").forward(request,response)
转发到BServlet - 从AServlet跳转到BServlet是服务器内部来控制的。对于浏览器而言,浏览器只发送了一个/a请求
重定向原理
- 假设发送了/a请求,执行了AServlet
- 在Aservlet中通过
response.sendRedirect("/webapproot/b")
重定向到BServlet - 此时浏览器会将请求路径
/webapproot/b
响应给浏览器 - 浏览器会自发的再次发送
/webapproot/b
请求来访问BServlet - 因此对于重定向来说,发送了两次请求,一次是
/webapproot/a
,另一次是/webapproot/b
SpringMVC实现转发和重定向
@RequestMapping("/a")
public String toA(){
return "a"; //转发到a
//return "forward:/b" //转发到b
//return "redirect:/b" //重定向到b
}
@RequestMapping("/b")
public String toB(){
return "b"
}
当return “a”;的时候,返回了一个逻辑视图名称,这种方式跳转到视图,默认采用的是forward方式跳转过去,只不过,底层创建的视图对象是ThymeleafView
当return “forward:/b”;转发到/b,这桑一次请求,底层创建的视图对象是InternalResourceView对象
当return “redirect:/b”;转发到/b这是两次请求,底层创建的视图对象是RedirectView对象
上述所提到的转发和重定向使用的return "forward:/b|redirect:/b"
中的/b
是请求资源的路径不是逻辑视图名称
若要使用重定向进行跨域,则必须在redirect后面写上全路径
访问静态资源
由于在web.xml文件中配置了springmvc的前端控制器映射,使得浏览器的所有请求都会走向springmvc的DispatcherServlet,而我们并没有配置关于静态资源的映射,因此不能直接访问静态资源
解决方法1
在Tomcat服务器中提供了一个默认的Servlet,叫做org.apache,catalina.servlets.DefaultServlet
在CATALINA_HOME/conf/web.xml文件中,有这个默认的Servlet的相关配置
要使用这个Servlet需要在springmvc.xml文件中配置<mvc:default-servlet-handler/> <mvc:annotation-driven>
当开启这个Servlet后默认会先走DispatcherServlet若发生404是会走DefaultServlet然后DefaultServlet会定位静态资源
解决方法2
在springmvc.xml中配置静态资源处理器
<mvc:resources mapping="/static/**" location="/static/" /> <mvc:annotation-driven/>
这里的配置是指当路径符合/static/**
的时候会去/static/
位置找资源