SpringMVC -- @ModelAttribute/视图,视图解析器/国际化(5)

@ModelAttribute 这个注解注释比较多.. 

我自己都有点看懵逼了...

还是在原来的例子上的Demo....

@ModelAttribute 和视图解析,以及国际化 我都写一起了,就不分开了..


SpringMVC -- @ModelAttribute/视图,视图解析器/国际化(5)_第1张图片


SpringMVC -- @ModelAttribute/视图,视图解析器/国际化(5)_第2张图片


package com.springmvc.handlers;

import com.springmvc.model.User;
import com.springmvc.model.User2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;

/**
 * Created by CYX on 2016/4/15.
 */

@SessionAttributes(value = {"user"},types = {String.class})
@RequestMapping("/main")
@Controller
public class Main {

    private static final String SUCCESS = "success";


    /**
     * 视图和视图解析器
     * 请求处理方法执行完成后,最终返回一个ModelAndView对象.
     * 对于那些返回String,View或ModeMap等类型的处理方法,SpringMVC也会在内部将他们装配成一个ModelAndView对象,它包含了逻辑名和模型对象的视图.
     *
     * SpringMVC借助视图解析器,得到最终的视图对象,最终的视图可以使JSP,也可能是Excel,JFreeChart等各种表现形式的视图.
     * 对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现MVC的充分解耦.
     *
     * 视图: 视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户.
     *      为了实现视图模型和具体实现技术的解耦,Spring在org.springframework.web.servlet 包中定义了一个高度抽象的View接口.
     *      视图对象由视图解析器负责实例化.由于视图是无状态的,所以他们不会有线程安全问题.
     *
     * 视图解析器: SpringMVC为逻辑视图名的解析提供了不同的策略,可以再SpringWEB上下文中配置一种或多种解析策略,并指定它们之间的先后顺序.
     *           每一种映射策略对应一个具体的视图解析器实现类.
     *           视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象.
     *           所有的视图解析器都必须实现ViewResolver接口.
     * @return
     */
    @RequestMapping("/testViewAndViewResolver")
    public String testViewAndViewResolver() {
        System.out.println("testViewAndResolver");
        return SUCCESS;
    }






    /**
     * 模拟提交用户表单数据,不提交用于密码,而是直接去数据库中获取,将要更新的参数更新.
     * 模拟修改操作
     * 1.原始数据为: 1,Tom,123456,[email protected],12
     * 2.密码不能被修改
     * 3.表单回显,模拟操作直接在表单填写对应的属性值
     *
     * 1.由@ModelAttribute标记的方法,会在每个目标方法执行之前被SpringMVC调用
     * 2.@ModelAttribute 注解也可以来修饰目标方法POJO类型的入参.其value属性值有如下的作用:
     *      (1).SpringMVC 会使用value属性值在 implicitModel 中查找对应的对象,若存在则会直接传入到目标方法的入参中.
     *      (2).SpringMVC 会一 value为key,POJO 类型的对象为value,存入到request中.
     * @param id
     * @param map
     */
    @ModelAttribute
    public void getUser2(@RequestParam(value = "id",required = false)Integer id,
                        Map<String,Object> map) {
        System.out.println("ModelAttribute method");
        if (id != null) {
            //模拟从数据库中获取对象
            User2 user2 = new User2(1, "Tom", "123456", "[email protected]", 12);
            System.out.println("从数据库获取一个对象: "+user2);
            map.put("abc", user2);
        }
    }

    /**
     * 运行流程:
     * 1.执行@ModelAttribute注解修饰的方法: 从数据库中取出对象,把对象放入到Map中,键位 user
     * 2.SpringMVC从Map中取出user对象,并把表单的请求参数,赋给该User对象的对应属性.
     * 3.SpringMVC把上述对象,传入目标方法的参数
     *
     * 注意: 在@ModelAttribute修饰的方法中,放入到Map中的键,需要和目标方法入参名字保持一致
     *
     * SpringMVC 确定目标方法POJO类型入参的过程.
     * 1.确定一个key
     *      (1).若目标方法的POJO类型的参数没有使用@ModelAttribute 作为修饰,则key 为 POJO 类名第一个字母的小写.
     *      (2).若使用了@ModelAttribute 来修饰,则 key 为@ModelAttribute 注解的value属性值.
     * 2.在implicitModel 中查找key对应的对象.若存在,则 作为入参传入.
     *      (1).若在@ModelAttribute 标记的方法中在Map 中保存过,且key 和 1 确定的key一致,则会获取到.
     * 3.若implicitModel 中不存在key对应的对象,则检查当前的Handler是否使用@SessionAttribute注解修饰.
     *   若使用了该注解, 且@SessionAttribute 注解的value属性值中包含了key,则会从HttpSession中来获取key所对应的value值,
     *   若存在则直接传入到目标方法中,若不存在则将抛出异常.
     * 4.若Handler 没有标示@SessionAttribute 注解 或 @SessionAttribute 注解的value值不包含key,则会通过反射来创建POJO类型的参数,传入目标方法的参数
     * 5.
     *
     *
     * 源码分析流程:
     * 1.首先调用@ModelAttribute 注解修饰的方法, 实际上是把 @ModelAttribute 方法中 Map 中的数据放在了implicitModel中.
     * 2.解析请求处理器的目标参数,实际上 该目标参数来自于 WebDataBinder 对象的 target 属性
     *      (1).创建WebDataBinder 对象:
     *          1).确定objectName属性 若传入的attrName 属性值为"",则 objectName为类名第一个字母小写.
     *              注意: attrName. 若目标方法的POJO属性使用了@ModelAttribute来修饰,则attrName 即为@ModelAttribute的value属性值.
     *          2).确定target属性
     *              > 在implicitModel中查找attrName对应的属性值. 若存在,OK
     *              > 若不存在:则验证当前Handler是否使用了@SessionAttributes 进行修饰,若使用了,则尝试从Session中获取attrName 所对应的属性值.
     *                若session  中没有对应的属性,则抛出异常
     *              > 若Handler没有使用@SessionAttribute 进行修饰,或@SessionAttribute 中没有使用value值指定的key和attrName相匹配,则通过反射创建POJO对象
     *
     *      (2).SpringMVC 把表单的请求参数赋给了WebDataBinder 的target对应的属性.
     *      (3).SpringMVC 会把WebDataBinder 的 attrName 和 target 给到implicitModel
     *      (4).把WebDataBinder 的tager 作为参数传递给目标方法的入参
     *      (5).SpringMVCh会把key 和 value 保存到implicitModel中,进而会保存到request中.
     *
     * @ModelAttribute("abc") 相当于给user2 这个名字 加上一个别名.这样子,abc 也可以 找到 user2 这个对象.
     *
     *
     * @param user2
     * @return
     */
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute( @ModelAttribute("abc") User2 user2) {
        System.out.println("修改: "+user2);
        return SUCCESS;
    }








    /**
     * @SessionAttributes
     * 若希望在多个请求之间共用某个某型属性数据,则可以在控制器类上标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂存到HttpSession中.
     * @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(Value属性值)
     * 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(types属性值)
     * 这个注解 只能放在类的上面.
     *
     *
     * @param map
     * @return
     */
    @RequestMapping("/testSessionAttributes")
    public String testSessionAttributes(Map<String,Object> map) {
        User user = new User("Tom","123456","[email protected]",15);
        map.put("user", user);
        map.put("school", "亚信");
        System.out.println();
        return SUCCESS;
    }

    /**
     * 处理模型数据的第二种方式
     * 目标方法可以添加Map类型的参数.
     *实际上也可以是Model类型,或ModelMap类型.
     *
     * @param map
     * @return
     */
    @RequestMapping("/testMap")
    public String testMap(Map<String,Object> map) {
        System.out.println(map.getClass().getName());
        map.put("names", Arrays.asList("Tom", "Jerry", "Mike"));
        System.out.println();
        return SUCCESS;
    }

    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView() {
        String viewName = SUCCESS;
        ModelAndView modelAndView = new ModelAndView(viewName);
        System.out.println("testModelAndView");
        modelAndView.addObject("time", new Date());
        modelAndView.addObject("str", "Hello");
        return modelAndView;
    }

    @RequestMapping("/testRequestParam")
    public String testRequestParam(@RequestParam(value = "username") String userName,
                                   @RequestParam(value = "age",required = false ,defaultValue = "0") Integer age) {
        System.out.println("testRequestParam userName: "+userName+", age: "+age);
        return SUCCESS;
    }

    @RequestMapping("/testPojo")
    public String testPojo(User user) {
        System.out.println("testPojo User:"+user);
        return SUCCESS;
    }

    @RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") Integer id) {
        System.out.println("testPathVariable id: "+id);
        return SUCCESS;
    }

    @RequestMapping(value = "/testMethod",method = RequestMethod.POST)
    public String testMethod() {
        System.out.println("testMethod POST");
        return SUCCESS;
    }

    @RequestMapping("/sayHello")
    public String sayHello() {
        System.out.println("Hello");
        return SUCCESS;
    }

}


success.jsp

<%--
  Created by IntelliJ IDEA.
  User: CYX
  Date: 2016/4/15
  Time: 22:38
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title></title>
</head>
<body>
Success Page!
<br>
<br>
time:${requestScope.time}
<br>
<br>
String:${requestScope.str}
<br>
<br>
names:${requestScope.names}
<br>
<br>
request user:${requestScope.user}

<br>
<br>
request user2:${requestScope.user2}

<br>
<br>
request school:${requestScope.school}
<br>
<br>
session user:${sessionScope.user}
<br>
<br>
session school:${sessionScope.school}

<br>
<br>
<fmt:message key="i18n.username"></fmt:message>
<fmt:message key="i18n.password"></fmt:message>

</body>
</html>


i18n_zh_CN.properties
i18n.username=\u7528\u6237\u540d
i18n.password=\u5BC6\u7801


i18n_en_US.properties

i18n.username=Username
i18n.password=Password


index.jsp

<%--
  Created by IntelliJ IDEA.
  User: CYX
  Date: 2016/4/15
  Time: 21:53
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title></title>
  </head>
  <body>



  <a href="/main/testViewAndViewResolver">testViewAndViewResolver</a>




  <!--
    模拟修改操作
    1.原始数据为: 1,Tom,123456,[email protected],12
    2.密码不能被修改
    3.表单回显,模拟操作直接在表单填写对应的属性值
  -->
  <br><br>
  <form action="main/testModelAttribute" method="post">
    <input type="hidden" name="id" value="1">
    <br>
    username:<input type="text" name="username" value="Tom">
    <br>
    email:<input type="text" name="email" value="[email protected]">
    <br>
    age:<input type="text" name="age" value="12">
    <br>
    <input type="submit" value="submit">
  </form>

  <br><br>
  <a href="main/testSessionAttributes">testSessionAttribute</a>

  <br><br>
  <a href="main/testMap">testMap</a>

  <br><br>
  <a href="main/testModelAndView">testModelAndView</a>

  <br><br>
  <a href="main/testRequestParam?username=cyx&age=11">testRequestParam</a>

  <br><br>
  <form action="main/testPojo" method="post">
    username:<input type="text" name="username"><br>
    password:<input type="text" name="password"><br>
    email:<input type="text" name="email"><br>
    age:<input type="text" name="age"><br>
    city:<input type="text" name="address.city"><br>
    province:<input type="text" name="address.province"><br>
    <input type="submit" value="PojoUserAddress对象">
  </form>

  <form action="main/testPojo" method="post">
    username:<input type="text" name="username"><br>
    password:<input type="text" name="password"><br>
    email:<input type="text" name="email"><br>
    age:<input type="text" name="age"><br>
    <input type="submit" value="PojoUser对象">
  </form>

  <br>
  <a href="main/testPathVariable/1">testPathVaiable id=1</a>

  <br>
  <form action="main/testMethod" method="post">
    <input type="submit" value="testMethodPost">
  </form>
  <a href="main/testMethod">testMethod Get</a>

  <br>
  <a href="main/sayHello">sayHello</a>
  </body>
</html>

dispatcher-servlet.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

       <context:component-scan base-package="com.springmvc.handlers"/>

       <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/WEB-INF/views/"></property>
              <property name="suffix" value=".jsp"></property>
       </bean>

       <!--配置国际化资源文件-->
       <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
              <property name="basename" value="i18n"></property>
       </bean>

</beans>

部署运行即可...

测试国际化的话,使用IE浏览器,切换Inter中的语言设置即可....



你可能感兴趣的:(SpringMVC -- @ModelAttribute/视图,视图解析器/国际化(5))