在spring MVC 中,controllers不会负责具体的页面渲染,它仅仅是调用业务逻辑并返回model数据给view层,至于view层具体怎么用HTML展示,由专门的view层具体负责,这就是MVC模式,业务层与展现层是松耦合的。那么,Spring MVC是如何解耦合请求处理逻辑和页面渲染的呢?java
咱们在Spring MVC配置介绍文章中已经知道,controller在处理外业务逻辑以后会返回一个逻辑view的字符串,那么Spring MVC是怎么根据这个逻辑view名找到真正的物理view页面呢?这个工做就由Spring的ViewResolvers负责。web
对于普通的JSP页面,最经常使用到的就是view resolver就是InternalResourceViewResolver
,它有两个属性,一个是匹配物理view的前缀,一个是后缀。前缀通常就是view页面的路径位置,后缀就是文件的格式,而前缀后缀之间的就是逻辑view名称。spring
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
好比按照上面的配置,若是controller返回的逻辑view名称是home的话,InternalResourceViewResolver
会根据这个逻辑view名home找到其对应的实际物理view:/WEB-INF/views/home.jsp
。编程
@Controller @RequestMapping(value = "/") public class HomeController { @RequestMapping(method= RequestMethod.GET) public String home() { return "home"; } }
ViewResolver接口:后端
public interface ViewResolver { View resolveViewName(String var1, Locale var2) throws Exception; }
这个接口很简单,当咱们传入一个逻辑view名和Locale对象,就会返回一个View实例。mvc
View接口:app
public interface View { String getContentType(); void render(Map<String, ?> var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception; }
View接口的职责就是接收model对象、Request对象、Response对象,并渲染输出结果给Response对象。若是咱们要本身写一个ViewResolver也很简单,咱们只须要实现ViewResolver和View两个接口,在View接口中把须要渲染的内容输出到Response对象中去就能够了。jsp
固然,咱们基本上不须要本身去写ViewResolver,spring mvc为咱们提供了各类各样的ViewResolver:
ui
上面虽然列了不少个ViewResolver,但咱们具体用哪一个好呢?其实上面的每一个ViewResolver都对应着一种view页面的实现技术,好比InternalResourceViewResolver
就是用来处理JSP页面,TilesViewResolver
主要处理Apache Tiles Views
,FreeMarkerViewResolver
和VelocityViewResolver
分别对应着FreeMarker
和Velocity Template
页面渲染技术。spa
无能否认,在Java web编程领域,历史最悠久的页面处理技术即是JSP。因此,这里咱们就拿JSP技术来展现spring是如何渲染页面的。
Spring有两种方式来支持JSP页面:
1. InternalResourceViewResolver能够用来解析JSP文件,固然,它也支持JSP页面使用JavaServer Standard Library(JSTL) 2. Spring本身也提供了两种JSP 标签类库,一种是表单数据绑定标签库,另外一种是提供了一些通用特性的标签库
不管咱们使用JSTL仍是Spring JSP标签类库,咱们都须要配置一个ViewResolver来解析JSP页面。固然一些其余的ViewResolver也能够解析JSP页面,但InternalResourceViewResolver是专门针对JSP技术设计的解析器,因此对于JSP页面,它用起来最简单也最方便。
其实InternalResourceViewResolver
的配置在1.1节已经介绍了,它能够直接把一个逻辑view名映射到转实际渲染数据的物理view页面。若是按照咱们这样的配置:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
那么对于下面这些逻辑view名,InternalResourceViewResolver
则会将其映射成相应的JSP页面:
上面例子中还能够看到,当咱们的逻辑名称中含有反斜线/时,解析器会将其解析成资源文件的路径,这样咱们就能够对页面资源文件进行目录管理了。
若是要想在JSP中使用JSTL标签很简单,咱们只需在InternalResourceViewResolver中指定一个viewClass属性便可:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView /> </bean>
上面已经讲过,Spring JSP提供了两种类库,一种是表单数据绑定标签库,另外一种提供了更多样话的通用标签库。
Spring的表单数据绑定标签库提供了14个标签,它和普通标签的区别就是可以将表单属性和model对象属性绑定在一块儿。要想使用表单数据绑定标签库,只须要在JSP页面中声明:
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
标签库中的14个标签:
下面举个例子,咱们使用这个标签库来重写一个注册页面:
<sf:form method="POST" commandName="user"> First Name: <sf:input path="firstName" /><br/> Last Name: <sf:input path="lastName" /><br/> Email: <sf:input path="email" /><br/> Username: <sf:input path="username" /><br/> Password: <sf:password path="password" /><br/> <input type="submit" value="Register" /> </sf:form>
commandName:对应后端model数据对象名称,也就是Model中的对应的key值
@RequestMapping(value="/register", method= RequestMethod.GET) public String showRegistrationForm(Model model) { model.addAttribute("user",new User()); return "register"; }
path:咱们能够看到form表单内部每一个标签都有个path属性,这个属性对应的就是Model对象的属性
除了表单数据绑定标签库以外,Spring还提供了一个更加通用的标签库,要想使用这个更通用的标签库,只须要在JSP页面中添加:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
标签库中的标签:
关于这些标签的详细使用说明能够查看spring的官方文档,这里很少作介绍了。