SpringMVC-04-视图/视图解析器
视图层
forward: 转发
和原本的 SpringMVC 一样,写在方法的返回值处,不过不同的是 forward: 不会被拼串,并且是以项目地址为相对路径的。
原:
1 |
|
forward:
1 |
|
redirect: 重定向
使用方法和 forward:
转发是一样的,和使用 response.sendRedirect("/XXX")
唯一不同的是,相对地址会自动加上项目地址,方便浏览器解析。
1 |
|
视图解析原理
这一段转自与知乎,其实自己也写了总结,但是觉得不太行,没有下文理解的清晰。
当我们对 SpringMVC 控制的资源发起请求时,这些请求都会被 SpringMVC 的 org.springframework.web.servlet.DispatcherServlet 处理,接着 SpringMVC 会分析看哪一个 HandlerMapping 定义的请求映射中存在对该请求的最合理的映射。然后通过该 HandlerMapping 取得其对应的 Handler(也就是我们定义的处理请求方法),接着再通过相应的 HandlerAdapter 处理该 Handler。HandlerAdapter 再对Handler 进行处理。
之后会返回一个 ModelAndView 对象。在获得了 ModelAndView 对象之后,Spring 就需要把该 View 渲染给用户,即返回给浏览器。在这个渲染的过程中,发挥作用的就是 ViewResolver 和 View。当 Handler 返回的 ModelAndView 中不包含真正的视图,只返回一个逻辑视图名称,ViewResolver 会把该逻辑视图名称解析为真正的视图 View 对象。View 真正进行视图渲染,把结果返回给浏览器。
而 ViewResolver 和 View 都是一个接口,定义如下:
1 | public interface ViewResolver { |
1 | public interface View { |
调用 View 对象的 render 渲染(指生成用户看到的 html 页面)方法,进行请求转发(并将模型输入放入 Request 域中),或者请求重定向。SpringMVC 主要负责的是生成 View 的过程,至于不同的 View 接口实现可以五花八门,实现了视图层的解耦。
使用 JstlView 实现国际化
在 Spring 中导入 taglibs-standard-impl 和 taglibs-standard-spec 这两个包之后,在 Spring 中配置的 InternalResourceViewResolver 中,添加 viewClass 属性值为 JstlView 之后,ViewResolver 将生成的 View 实例从原本的 InternalResourceView 更改为更强大的子类:JstlView。
这个 View 强大之处就是大大简化了国际化的配置与使用。
首先搞几个不同国家地区的文字:i18n_en_US.properties
和 i18n_zh_CN.properties
。然后在 Spring 中配置:
1 | <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> |
需要注意 id 一定要是 messageSource
,Spring 是根据这个 id 名字来寻找绑定的国际化信息的。然后在相关的 jsp 页面引入 fmt 标签,然后使用 <fmt:message>
来输出国际化信息。
1 | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> |
请求页面跳转访问
因为很多强大的功能只有经过 SpringMVC 才能实现,比如上面的国际化,这就需要我们对一些直接访问的资源经过 SpringMVC 处理,或者访问 WEB-INF 下面的资源,也需要进行请求转发才可以获取资源。那么大量的仅仅只进行请求转发的处理方法写起来太乱了,可以直接用一条 Spring 的配置解决。
1 |
|
SpringMVC 支持通过配置的方法,来实现访问地址直接向 WEB-INF 下资源的访问:
1 | <mvc:view-controller path="/login" view-name="Login" /> |
但是需要注意的是,使用了 mvc:view-controller
来接管对请求路径的访问之后,会打断原本注解标注的 @RequestMapping
,需要额外添加一个 mvc:annotation-driven
来进行扫描注解接管请求映射。
自定义视图解析器
大致过程:首先实现 ViewResolver 和 View 两个接口。ViewResolver 还需要实现 Ordered ,来将优先级提高到高于 InternalResourceViewResolver,只需要获取的 order 值越低,权重越高!
如果开头是 Tempest ,则确认为本 ViewResolver 处理对象,返回一个本 ViewResolver 生成的 View 对象:
1 | public class MyViewResolver implements ViewResolver, Ordered { |
这个 View 的渲染方式就是转发请求到指定的页面中:
1 | public class MyView implements View { |
然后记得将自己实现的 ViewResolver 添加到 IOC 容器(配置文件注册 bean 的 class 即可)中,Spring 会根据是否实现 ViewResolver 接口决定此类是否为视图解析类,并在控制 View 生成的时候,依次调用所有的 ViewResolver 的 resolveViewName() 方法。所以必须让 Spring 知道自己才有可能被调用去生成 View。
1 | <bean class="space.xorex.SpringMVC.ViewResolver.MyViewResolver"> |
然后我们再进行请求映射:
1 |
|
这样当我们发起 XXXX/test/
的请求的时候,就会将 Tempest:hello
视图名根据 order 权重依次传入 ViewResolver 的 resolveViewName() 中,我们写的 ViewResolver 看到了 Tempest:
的开头,匹配成功并返回我们自己实现的 View:MyView,最后调用 MyView 的渲染方法 render() 并执行我们指定的请求转发代码。