渲染web视图

6将模型数据渲染成HTML

6.1 理解视图解析

在MVC模型中,控制器将数据填充到模型中,然后将模型传递给一个用来渲染的视图。控制器中返回的String类型的值是视图的名称。
逻辑处理和视图渲染是解耦的,控制器方法和视图在模型内容上达成一致,除此之外再无关联。

Spring MVC中定了一个名为ViewResolver的接口作为视图解析器,它将返回一个View接口,而View接口将会接收模型和Servlet的request和response,然后将结果写会response。

public interface ViewResolver{
    View resolveViewName(String viewName, Locale locale) throw Exception;
}
public interface View{
String getContentType();
void render(Map model, HttpServletRequest request, HttpServeltResponse response) throws Exception;
}

Spring 自带了13个视图解析器,所以大部分情况下我们不需要自己实现ViewResolver。大多数情况下我们只使用极少的几个就可以了。

InternalResourceViewResolver用于解析JSP
FreeMarkerViewResolver用于解析FreeMarker模板视图
VelocityViewResolver模板视图。

6.2 创建JSP视图

Spring 支持两种JSP视图模式

  • InternalResourceViewResolver会将视图名解析为JSP库,稍加设置可以使用JSTL
  • Spring提供了2种标签库,一种用于表单和模型的绑定,另一种提供了通用的工具类特性。

6.2.1 配置适用于JSP的视图解析器

根据前缀和后缀来解析

使用Bean注解配置

@Bean
public ViewResolver viewResolver(){
InternalResorceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);//这句话用于JSTL标签库。
return resolver;
}

使用xml配置

<bean id="viewResovler"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    p:prefix="/WEB-INF/views/"
    p:suffix=".jsp"
    --下面这行用于JSTL标签库-->
    p:viewClass="org.springframework.web.servlet.view.JstlView"
/>

6.2.2 使用Spring的JSP标签库

Spring 提供了两个标签库,
一个标签库用来渲染html表单标签,绑定表单和模型;另一个包含了一些工具标签。

对于表单标签库,其一个典型的作用就是讲填写表单的元素绑定到表单上,这样的好处之一就是可以验证填写表单的元素,然后重填的时候可以使用模型来自动填充之前填写的数据,并且使用特殊的样式来标记错误的表单项。

这里举一个例子:
比如你有一个需要注册的用户信息如下:

package com.zhaoch93.EmailManager.po;

import org.hibernate.validator.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {
    @NotNull
    @Size(min=5,max = 35,message = "{username.size}")
    private String username;
    @NotNull
    @Size(min=5,max = 35,message = "{password.size}")
    private String password;
    @NotNull
    @Email(message = "{email.valid}")
    private String bingemail;

    public User() {
    }

    public User(String username, String password, String bingemail) {
        this.username = username;
        this.password = password;
        this.bingemail = bingemail;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getBingemail() {
        return bingemail;
    }

    public void setBingemail(String bingemail) {
        this.bingemail = bingemail;
    }
}

这是要一个简单的POJO,但是在属性上有一些标注,比如@NotNull,@Size@Email等等。
这些注解是JSR-303的数据验证规范,属于JAVA EE的规范一部分,hibernate-validator是这个规范的实现,在实现的过程中还拓展了一些,比如@Email就是JSR规范中没有的,是实现自己做了拓展。
所以上面这个POJO想要具体发回功能还需要把hibernate-validator加入到路径中,此外还有一个常识性的问题,就是要加。只有完成这些才有效。

然后是JSP的部分

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<%@ page session="false" %>
<html>
<head>
    <title>Spittertitle>
    <link rel="stylesheet" type="text/css"
          href="/css/style.css" >
head>
<body>
<h1>Registerh1>

<sf:form method="POST" commandName="user" >
    <sf:errors path="*" element="div" cssClass="errors" />
    <sf:label path="bingemail" cssErrorClass="error">Emailsf:label>:
    <sf:input path="bingemail" cssErrorClass="error" /><br/>
    <sf:label path="username"  cssErrorClass="error">Usernamesf:label>:
    <sf:input path="username"  cssErrorClass="error" /><br/>
    <sf:label path="password"  cssErrorClass="error">Passwordsf:label>:
    <sf:password path="password" cssErrorClass="error" /><br/>
    <input type="submit" value="Register"/>
sf:form>
body>
html>

taglib里面的是固定的,但是sf可以自由选择其他的字段代替。
form中commandName后需要填的是绑定的模型的名字,借助自动推断功能,我们可以用User的小写模式。当然在进入这个registerform.jsp之前模型里面需要有user键值对才行。这里可以通过Controller层进行添加。

Controller的java代码如下:

package com.zhaoch93.EmailManager.controller;

import com.zhaoch93.EmailManager.po.User;
import com.zhaoch93.EmailManager.service.IUserService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;

@Controller
public class AuthController {

    @RequestMapping(value = "/register",method = RequestMethod.GET)
    public String showRegisterationForm(Model model){
        model.addAttribute(new User());
        return "registerform";
    }

    @RequestMapping(value="/register", method=RequestMethod.POST)
    public String processRegistration(
            @Valid User user,
            Errors errors) {
        if (errors.hasErrors()) {
            return "registerform";
        }
        return "access";
    }
}

这里代码很简单,在get阶段添加一个model进去,名字就是自动推断的user,当然你也可以自己改一个key,相应的jsp中的commandName也要变了。在Post阶段进行验证,如果验证通过就进入access,如果验证失败就重新进入registerform,这时之前的model还带,并且会根据设定的css来显示不同样式。


JSP通用工具的标签库不介绍了

6.3 使用Apache Tiles视图定义布局

6.4 使用Thymeleaf

你可能感兴趣的:(读书笔记,JAVA,web,spring,mvc,web,html)