`
ccii
  • 浏览: 54977 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

SpringMVC

阅读更多
一、Spring概述
1. 简介
    Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。Spring框架在框架设计、扩展性、灵活性等方面全面超越了Struts、WebWork等MVC框架,从原来的追赶者一跃为MVC的领跑者。Spring框架围绕DispacherServlet这个核心展开,它负责截获请求并将其分派给相应的处理器处理。

2. Spring MVC和Struts2的比较
(1)Spring MVC的入口是servlet,而Struts2是filter,这里要指出filter和servlet是不同的。
(2)Spring MVC会稍微比Struts2快。Spring MVC是基于方法的设计,方法级别的拦截。而struts2设计是基于类,采用类级别的拦截。
(3)参数传递方面,Struts2用属性的get方法接受参数,这就说明参数是让多个方法共享的。
(4)配置文件方面很明显Struts2要复杂的多。

二、Spring MVC示例
1. 在web.xml中配置DispatcherServlet
    DispatcherServlet是Spring MVC的灵魂和心脏,它负责接收HTTP请求并协调Spring MVC的各个组件完成请求处理的工作。和任何Servlet一样,用户必须在web.xml中配置好DispatcherServlet。如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
 <!-- 指定业务层Spring容器的配置文件,多个用逗号隔开 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:config/spring-config.xml</param-value>
    </context-param>
   
    <!-- 通过contextConfigLocation指定的配置文件启动业务层的Spring容器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 <!-- 配置名为spring的DispatcherServlet,默认自动加载/WEB-INF/spring-servlet.xml的配置文件,启动Web层的Spring容器。
 一个web.xml可以配置多个DispatcherServlet -->
 <!-- 这里,WEB层Spring容器将作为业务层Spring容器的子容器,即WEB层容器可以引用业务层容器的Bean,而业务层却不能访问WEB层容器的Bean -->
     <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定使用类路径下的WEB层spring容器配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:config/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
 <!-- 指定DispatcherServlet处理所有URL以.html为后缀的HTTP请求 -->
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
</web-app>


2. 编写处理请求的控制器
    Spring MVC通过一个@Controller注解即可将一个POJO转化为处理器请求的控制器,通过@RequestMapping为控制器指定处理哪些URL的请求。如下:

UserController.java:
package com.jiang.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.jiang.web.entity.User;
//标注UserController成为处理请求的控制器
@Controller
//处理来自/user URI的请求,限定请求路径为/user下,此路径可以不加
@RequestMapping("/user")
public class UserController {
    //直接处理“/user.html”的请求,请求的方法必须为POST
    @RequestMapping(method = RequestMethod.POST)
    //将表单值映射到User对象中
    public ModelAndView cteateUser(User user) {
        //注意此处的ModelAndView是在org.springframework.web.servlet包下,不要import错了
        ModelAndView mav = new ModelAndView();
        mav.setViewName("menu");
        mav.addObject("user", user);
        return mav;
    }
    //将处理http://127.0.0.1:8080/WalletManager/user/login.html的请求
    @RequestMapping("/login")
    public String index() {
        //返回一个逻辑视图名,根据配置文件映射为/WEB/INF/customer/login.jsp
        return "login";
    }
}


User.java:
package com.jiang.web.entity;
public class User {
    private String userName;
    private String password;
    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;
    }
}


3. 编写视图对象
WEB-INF/customer/login.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8"
 pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>登陆</title>
</head>
<body>
 <!-- 将表单提交到/user.html控制器中, -->
 <form method="post" action="/user.html">
  <table>
   <tr>
    <td>用户名:</td>
    <td><input type="text" name="userName" /></td>
   </tr>
   <tr>
    <td>密码:</td>
    <td><input type="password" name="password" /></td>
   </tr>
   <tr>
    <td><input type="submit" value="登陆" /></td>
   </tr>
  </table>
 </form>
</body>
</html>


WEB-INF/customer/menu.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>新会员中心</title>
</head>
<body>
 Wellcome! ${user.userName}
</body>
</html>


4. 配置Spring MVC的配置文件
spring-config.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"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
</beans>


spring-mvc.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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
   
    <!-- 让Spring扫描包下标注注解的类生效 -->
    <context:component-scan base-package="com.jiang.web.controller"/>
     
    <!-- 定义一个视图名称解析器,将名称解析为/WEB-INF/customer/名称.jsp -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     <property name="prefix" value="/WEB-INF/customer/"></property>
     <property name="suffix" value=".jsp"></property>
    </bean>
</beans>


5. SpringMVC处理user.html过程描述
(1)DispatcherServlet接收到客户端的user.html的请求
(2)DispatcherServlet使用DefaultAnnotationHandlerMapping查找负责处理该请求的处理器为user.html
(3)DispatcherServlet将请求分发给名为user.html的UserController处理器
(4)处理器完成业务处理后,返回ModelAndView对象,其中View的逻辑名为menu,模型包含一个键为user的User对象
(5)DispatcherServlet调用InternalResourceViewResolver组件对ModelAndView中的逻辑视图名进行解析,得到真实的/WEB-INF/customer/menu.jsp视图对象
(6)DispatcherServlet使用/WEB-INF/customer/menu.jsp对模型中的user模型对象进行渲染
(7)返回响应页面给客户端

三、注解驱动的控制器
1. 使用@RequestMapping映射请求
    在POJO类定义处标注@Controller,再通过<context:component-scan base-package="com.jiang.web.controller"/>扫描相应的类包,即可使POJO成为一个能处理HTTP请求的控制器。然后在控制器的类定义及方法定义处都可标注@RequestMapping,类定义处提供初步请求映射信息,方法处提供进一步的细分映射信息。
    将请求映射到控制器处理方法的工作包含一系列的映射规则,这些规则是根据请求中的各种信息制定的,具体包括请求URL、请求参数、请求方法、请求头这4个方面的信息项。

(1)通过请求URL进行映射
    @RequestMapping("/user"),它不但支持标准的URL,还支持Ant风格(即?、*和**的字符)的和带{xxx}占位符的URL。如下:
    /user/*/createUser:匹配/user/aaa/createUser、/user/bbb/createUser等URL
    /user/**/createUser:匹配/user/createUser、/user/aaa/bbb/createUser等URL
    /user/createUser??:匹配/user/createUseraaa、/user/createUserbbb等URL
    /user/{userId}:匹配/user/123、/user/234等URL
    /user/**/{userId}:匹配/user/aaa/bbb/123等URL
    /company/{companyId}/user/{userId}/detail:匹配/company/123/user/456/detail等URL

    URL中的{xxx}可以通过@PathVariable将URL中的占位符参数绑定到控制器处理方法的入参中,类和方法处的占位符都可以绑定到处理方法的入参中,如下:
    @RequestMapping("owners/{ownerId}")
    public class UserController{
      @RequestMapping("users/{userId}")
      public ModelAndView showDetail(@PathVariable("ownerId")String ownerId,@PathVariable("userId")String userId){
        ..
      }
    }

    注意,要使用上面的入参成功绑定URL中的占位符,必须在编译时开启debug开关。

(2)通过请求参数、请求方法或请求头进行映射让请求映射更加精确化



    @RequestMapping的value、method、params及headers分别表示请求URL、请求方法、请求参数及报文头的映射条件,它们之间是与的关系,联合使用多个条件项可让请求映射更加精确化。
    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping(value="/delete",method = RequestMethod.POST,params="userId")
        public String test1(@PathVariable("userId")String userId) {
            return "user/test1";
        }
        @RequestMapping(value="/show",headers="content-type=text/*")
        public String test2(@PathVariable("userId")String userId) {
            return "user/test2";
        }
    }


2. 请求处理方法的签名
    处理方法的签名包括对方法及方法入参标注相应的注解、入参、返回值等。对于这些签名,SpringMVC会优雅的将Http请求的信息绑定到相应的方法入参中,并根据方法返回值类型作出相应的后续处理。

(1)使用@RequestParam绑定请求参数值
    @RequestMapping(value="/handle")
    public String handle(
        @RequestParam(value="userName",required=false)String userName,
        @RequestParam(value="age")int age) {
        ...
    }
    上面的实例将“UserName”和“age”请求参数分别绑定到handle()方法的userName和age中,并自动完成类型转换。required参数表示请求中是否必须包含对应的参数,默认为true,上面的实例如果不存在age请求参数,将抛出异常。还有一个defaultValue参数设置默认参数名,不推荐使用该参数。

(2)使用@CookieValue绑定请求中的Cookie值
    @RequestMapping(value="/handle")
    public String handle(
        @CookieValue(value="sessionId",required=false)String sessionId,
        @RequestParam(value="age")int age) {
        ...
    }
    value指定Cookie的名称,required为false表示请求中没有相应的Cookie时也不会报错。

(3)使用@RequestHeader绑定请求报文头的属性值
    @RequestMapping(value="/handle")
    public String handle(
        @RequestHeader("Accept-Encoding")String encoding,
        @RequestHeader("Keep-Alive")long keepAlive) {
        ...
    }
    参数和@RequestParam相同。

(4)使用命令/表单对象绑定请求参数值
    @RequestMapping(value="/handle")
    public String handle(User user) {
        ...
    }
    所谓命令/表单对象并不需要实现任何接口,仅是一个拥有若干属性的POJO,Spring MVC会按请求参数名和命令/表单对象属性名匹配的方式,自动对该对象填充属性值。支持级联的属性名,如address.addressName。

(5)使用Servlet API对象作为入参
    在Spring MVC中,控制器类可以不依赖任何Servlet API对象,但是Spring MVC并不阻止我们使用Servlet API的类作为处理方法的入参。

    @RequestMapping(value="/handle")
    public void handle(HttpServletRequest request,HttpServletResponse response) {
        ...//同时使用HttpServletRequest和HttpServletResponse作为入参
           //使用HttpServletResponse返回响应时,将处理方法返回值设成void即可
           String userName = WebUtils.findParameterValue(request,"userName");
           response.addCookie(new Cookie("userName", userName));
    }

    @RequestMapping(value="/handle")
    public String handle(HttpServletRequest request) {
        ...//只使用HttpServletRequest作为入参,可返回String或ModelAndView
    }

    @RequestMapping(value="/handle")
    public String handle(HttpSession session) {
        ...//使用HttpSession作为入参,可返回String或ModelAndView
    }

    @RequestMapping(value="/handle")
    public String handle(HttpServletRequest request, @RequestParam(value="userName",required=false)String userName) {
        ...//同时使用HttpServletRequest和基本类型作为入参,它们之间的位置不固定
    }

    Spring MVC在org.springframework.web.context.request包中定义了若干个可代理Servlet原生API类的接口,它们也可以作为处理类的入参,通过这些类可访问请求对象的任何信息。
    @RequestMapping(value="/handle")
    public String handle(WebRequest request) {
        ...//使用Spring MVC的WebRequest作为入参
    }

(6)使用IO对象作为入参
    Servlet的ServletRequest拥有getInputStream()和getReader()方法,可以通过它们读取请求的信息。相应Servlet的ServletResponse拥有getOutputStream()和getWriter()方法,可以通过它们输出响应信息。
    Spring MVC允许控制器的处理方法使用java.io.InputStream/java.io.Reader及java.io.OutputStream/java.io.Writer作为方法的入参,Spring MVC将获取ServletRequest的InputStream/Reader或ServletResponse的OutputStream/Writer,然后传递给控制器的处理方法。如下:

    @RequestMapping(value="/handle")
    public String handle(OutputStream os) throws IOException {
        Resource res = new ClassPathResource("/image.jpg");
        FileCopyUtils.copy(res.getInputStream(), os);//将图片写到输出流
    }

(7)其它类型的参数
    控制器处理方法的入参除支持以上类型的参数以外,还支持java.util.Locale、java.security.Principal,可以通过Servlet的HttpServletRequest的getLocal()及getUserPrincipal()得到相应的值。如果处理方法的入参类型为Locale或Principal,Spring MVC自动从请求对象中获取相应的对象并传递给处理方法的入参。

3. 使用HttpMessageConverter<T>
    HttpMessageConverter<T>是Spring3.0新添加的一个重要接口,它负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。
    DispatcherServlet默认已经安装了AnnotationMethodHandlerAdapter作为HandlerAdapter的组件实现类,HttpMessageConConverter即由AnnotationMethodHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。
   
    Spring为HttpMessageConverter<T>提供了众多的实现类,它们组成了一个功能强大、用途广泛的HttpMessageConverter<T>家族,如下:
        StringHttpMessageConverter    将请求信息转换为字符串,默认装配;
        FormHttpMessageConverter    将表单数据读取到MultiValueMap中;
        XmlAwareFormHttpMessageConverter    扩展于FormHttpMessageConverter,如果部分表单属性是XML数据,可用该转换器进行读取,默认装配;
        ResourceHttpMessageConverter    读写org.springframework.core.io.Resource类型;
        BufferedImageHttpMessageConverter    读写BufferedImage对象;
        ByteArrayHttpMessageconverter    读写二进制数据,默认装配;
        SourceHttpMessageConverter    读写javax.xml.transform.Source类型的数据,默认装配;
        MarshallingHttpMessageConverter    通过Spring的org.springframework.oxm.Marshaller(将Java对象转换成XML)和Unmarshaller(将XML解析为Java对象)读写XML消息;
        Jaxb2RootElementHttpMessageConverter     通过JAXB2读写XML消息,将请求消息转换到标注XmlRootElement和XmlType注解类型中;
        MappingJacksonHttpMessageConverter      通过利用Jackson开源类包的ObjectMapper读写JSON数据;
        RssChannerHttpMessageConverter    能够读写RSS种子消息;
        AtomFeedHttpMessageConverter    和RssChannerHttpMessageConverter能够读写RSS种子消息;

    上面标明默认装配的实现类已装配到AnnotationMethodHandlerAdapter,如果需要装配其他类型,可以Spring的的Web容器上下文中自行定义一个AnnotationMethodHandlerAdapter,如下:
        <!-- 定义一个AnnotationMethodHandlerAdapter,显式定义后将覆盖默认的AnnotationMethodHandlerAdapter -->
        <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" p:messageConverters-ref="messageConverters"/>
        <util:list id="messageConverters">
            <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
            .....
        </util:list>

    使用HtpMessageConverter<T>,将请求信息转化并绑定到处理方法的入参中。
(1)使用@RequestBody / @ResponseBody对处理方法进行标注(p540)
(2)使用HttpEntity<T> / ResponseEntity<T>作为处理方法的入参或返回值(p542)
       
示例:处理JSON
(1)首先为AnnotationMethodHandlerAdapter装配上可处理JSON的HttpMessageConverter:
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list >
                <ref bean="mappingJacksonHttpMessageConverter" />
            </list>
        </property>
    </bean>
   
    <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
     <property name="supportedMediaTypes">
         <list>
             <value>application/json; charset=UTF-8</value>
             <value>text/html; charset=UTF-8</value>
        </list>
     </property>
 </bean> 


(2)在控制器编写相应的方法:
   
@RequestMapping("/product")
    @ResponseBody
    public List<Product> findProductList() {
        List<Product> liProduct= new ArrayList<Product>();
        for (ProductCodeEnum t : ProductCodeEnum.values())
        {
         Product product = new Product();
            product.setId(t.getCode());
            product.setText(t.getCnName());
            product.setLeaf(true);
           
            liProduct.add(product);
        }
        return liProduct;
    }


    注意,处理JSON必须引入下面四个包:
 
<dependency> 
   <groupId>org.codehaus.jackson</groupId> 
      <artifactId>jackson-core-lgpl</artifactId> 
      <version>1.9.13</version> 
  </dependency> 
  <dependency> 
   <groupId>org.codehaus.jackson</groupId> 
      <artifactId>jackson-core-asl</artifactId> 
      <version>1.9.13</version> 
  </dependency> 
  <dependency> 
  <groupId>org.codehaus.jackson</groupId> 
      <artifactId>jackson-mapper-asl</artifactId> 
      <version>1.9.13</version> 
  </dependency> 
  <dependency> 
      <groupId>org.codehaus.jackson</groupId> 
      <artifactId>jackson-mapper-lgpl</artifactId> 
      <version>1.9.13</version> 
  </dependency> 


4. 处理模型数据
    对于MVC框架来说模型数据是最重要的,因为控制层(C)是为了产生模型数据(M),而视图(V)则是为了渲染模型数据。
(1)ModelAndView
    控制器处理方法的返回值如果为ModelAndView,则其既包含视图信息,也包含模型数据信息。可以简单地将模型数据看成一个Map<Stirng, Object>对象。ModelAndView操作如下:
        ModelAndView addObject(String attributeName, Object attribute Value);  //添加模型数据
        ModelAndView addAllObjects(Map<String, ?> modelMap);  //添加模型数据
        void setView(View view);  //指定一个具体的视图对象
        void setViewName(String viewName);  //指定一个逻辑视图名

(2)ModelAttribute
    如果希望将方法入参对象添加到模型中,只需在相应入参前使用@ModelAttribute注解或在方法定义处使用@ModelAttribute注解即可。
        @RequestMapping(value = "/handle61")
        // SpringMVC将请求消息绑定到User对象中,然后再以“user”为键将User对象放到模型中。
        public String handle61(@ModelAttribute("user") User user) {
            user.setUserId("1000");
            return "/user/createSuccess";
        }

        @ModelAttribute("user")
        public User getUser() {
            User user = new User();
            user.setUserId("1001");
            user.setUserName("<>");
            return user;
        }
    当访问此控制器类中的任何一个请求处理方法前,都会事先执行标注了@ModelAttribute的getUser()方法,并将其返回值以user为键添加到模型中。

(3)Map及Model
    入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或java.util.Map时处理方法返回时,Map中的数据会自动添加到模型中。
        @RequestMapping(value = "/handle63")
        public String handle63(ModelMap modelMap) {
            User user = (User) modelMap.get("user");
            user.setUserName("tom");
            modelMap.addAttribute("testAttr", "value1");
            return "/user/showUser";
        }

(4)SessionAttributes
    将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性
        // 将handle71处的模型属性自动保存到HttpSession中
        @SessionAttributes("user")

        @RequestMapping(value = "/handle71")
        public String handle71(@ModelAttribute("user") User user) {
            user.setUserName("John");
            return "redirect:handle72.html";  //向handle72发起一个新的请求
        }
        @RequestMapping(value = "/handle72")
        public String handle72(ModelMap modelMap, SessionStatus sessionStatus) {
            User user = (User) modelMap.get("user");  //读取模型中的数据
            if (user != null) {
                user.setUserName("Jetty");
                sessionStatus.setComplete();  //让SpringMVC清除本处理器对应的会话属性
            }
            return "/user/showUser";
        }

四、处理方法的数据绑定
    在请求消息到达真正调用处理方法的这一段时间内,Spring MVC还完成了很多工作,包括数据转换、数据格式化及数据校验等。
1. 数据绑定流程
    Spring MVC通过反射机制对目标处理方法的签名进行分析,将请求消息绑定到处理方法的入参中。
(1)Spring MVC主框架将ServletRequest对象及处理方法的入参对象实例传递给DataBinder
(2)DataBinder调用装配在Spring Web上下文中的ConversionService组件进行数据类型转换、数据格式化的工作,将ServletRequest中的消息填充到入参对象中。
(3)DataBinder对象继续调用Validator组件对已经绑定了请求消息数据的入参对象进行数据合法性校验。最终生成BindingResult对象,将它们赋给处理方法的入参。

2. 数据转换
    Spring3.0在核心模型中添加了一个通用的类型转换模块,位于org.springframework.core.convert包中,同时支持Java标准的PropertyEditer。
(1)ConversionService是Spring类型转换体系的核心接口。
(2)Spring支持的转换器
    Converter<S,T>
    GenericConverter
    ConverterFactory
(3)在Spring MVC中使用ConversionService自定义转换器

3. 数据格式化
    Spring3.0引入了一个新的格式化框架,位于org.springframework.format包中,
(1)Formatter<T>是格式化框架最重要的接口
(2)注解驱动格式化的重要接口
(3)启用注解驱动格式化功能
(4)注解驱动格式化实例

4. 数据校验
(1)JSR303是Java为Bean数据合法性校验所提供的标准框架,它已经包含在Java EE6.0中。通过在Bean属性上标注类似于@NotNull等标准的注解指定校验规则
(2)Spring校验框架,它在org.springframework.validation包下,通过注解驱动的方式进行数据校验。
(3)Spring数据校验(获取校验结果、如何在页面中显示错误、通过国际化资源显示错误信息)
(4)自定义校验规则(为请求处理类装配一个自定义的Validator)

五、视图和视图解析器
    请求处理方法执行完成后,最终返回一个ModelAndView对象,对于那些String、View或ModelMap等类型的处理方法,SpringMVC也会在内部将它们装配成一个ModelAndView对象,它包含了实图逻辑名和模型对象的信息。
1. 视图,是渲染模型数据,将模型里的数据以某种形式呈现给客户(JSP、Excel、PDF等)。
2. 视图解析器,将逻辑视图名解析为一个具体的视图对象。
3. JSP和JSTL
(1)使用InternalResourceViewResolver作为视图解析器(JSP)
(2)使用Spring表单标签,它可以很容易地将模型数据中的表单/命令对象绑定到HTML表单元素中
4. 模板视图
    FreeMarker和Velocity是除了JSP之外被使用最多的页面模板技术。页面模板编写好页面结构,模板页面中使用一些特殊的变量标识符绑定Java对象的动态数据。
5. Excel
    如果希望使用Excel展示用户列表,仅需要扩展Spring的AbstractExcelView或AbstractJExcelView即可。
6. PDF
    PDF视图和Excel类似,也是使用一个Bean作为视图对象
7. XML
    将模型中的数据以XML的形式输出,对应视图对象为MarshallingView
8. JSON
    SpringMVC的MappingJacksonJsonView借助Jackson框架的ObjectMapper将模型数据转换为JSON格式输出。
    默认情况下,MappingJacksonJsonView会将模型中的所有数据都输出为JSON,这显然是不适合的,可以通过renderedAttravutes指定模型中哪些属性需要输出。
9. XmlViewResolver
    同BeanNameViewResolver,但它可以将视图Bean定义在一个独立的XML文件中
10. ResourceBundleViewResolver
    它通过一个国际化资源文件定义视图对象,为不同地区的用户提供不同类型的视图
11. 混合使用多种视图技术
(1)ContentNegotiatingViewResolver
(2)使用同一URL获取不同形式的返回内容

六、本地化解析
1. 本地化概述
    浏览器中设置的本地化类型会包含在HTML请求报文头中发送给Web服务器,确切地说是通过报文头的Accept-Language参数将“语言首选项”对话框中选择的语言发送到服务器,成为服务器判别客户端本地化类型的依据。可以通过IE菜单:工具--Internet选项--语言--选择本地化类型设置。

2. 使用CookieLocaleResolver,DispactcherServlet会自动识别本地化解析器并装配它。
3. 使用SessionLocaleResolver,查找Session中属性名为SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME的属性,并将其转换为Locale对象。
4. 使用LocaleChangeInterceptor,通过一个请求参数控制网站的本地化。

七、文件上传
    SpringMVC为文件上传提供了即插即用的MultipartResolver,采用了Jakarta Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver。
1. 配置MultipartResolver
 <!-- 文件上传 -->
 <bean id="multipartResolver"
   class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
          p:defaultEncoding="UTF-8"
          p:maxUploadSize="5000000"
          p:uploadTempDir="upload/temp"/>  


2. 编写控制器
 @RequestMapping(value = "/upload") 
 public String updateThumb(@RequestParam("name") String name,
                     @RequestParam("file") MultipartFile file) throws Exception{
  if (!file.isEmpty()) {
   file.transferTo(new File("d:/temp/"+file.getOriginalFilename()));
   return "redirect:success.html";
  }else{
   return "redirect:fail.html";
  }
 }


SpringMVC会将上传文件绑定到MultipartFile对象中。使用如下:
    byte[] getBytes():获取文件数据
    String getContentType():获取文件MIME类型
    InputStream getInputStream():获取文件流
    String getName():获取表单中文件组件的名字
    String getOriginalFilename():获取上传文件的原名
    long getSize():获取文件的字节大小,单位byte
    boolean isEmpty():是否有上传的文件
    void transferTo(File dest):将上传文件保存到一个目标文件中

3. 表单
    负责上传文件的表单编码必须是“multipart/form-data”类型。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
 <head>
  <title>请上传用户头像</title>
 </head>
 <body>
  <h1>
   请选择上传的头像文件
  </h1>
  <form method="post" action="<c:url value="/user/upload.html"/>" enctype="multipart/form-data">
   <input type="text" name="name" />
   <input type="file" name="file" />
   <input type="submit" />
  </form>
 </body>
</html>


八、其它
1. 静态资源处理
(1)将DispatcherServlet请求映射配置为"/",使其捕获Web容器所有的请求。
    <filter>
        <filter-name>Set Character Encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>Set Character Encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


(2)Spring MVC配置
    方法一:
    <!-- 如果是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,-->
    <mvc:default-servlet-handler/>
   
    方法二:
    <!-- 由Spring MVC框架自己处理静态资源,将Web根路径“/”及类路径下/META-INF/publicResources/的目录映射为/resources路径。假设Web根路径下拥有js/ext.js,则在jsp则可通过 "/resources/js/ext.js访问" -->
    <mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/publicResources/"/>  
    <mvc:resources/>允许静态资源放在任何地方,如WEB-INF目录下、类路径下等。在接收到静态资源的获取请求时,会检查请求头的Last-Modified值,如果静态资源没有发生变化,则直接返回303响应状态码,指示客户端使用浏览器缓存的数据,而非将静态资源的内容输出到客户端。如果在映射的物理路径下存在多个同名静态资源,找到第1个就返回,查找的顺序和物理路径在location中的配置顺序一致。
    <mvc:resources mapping="/resources/**"
location="/" cache-period="31536000"/>   
    通过cache-period属性设置静态资源在客户端浏览器中的缓存有效时间,一般设置为一年。

    有时由于浏览器本身缓存管理机制的问题,当我们发布新的版本时客户端并不会从服务器端下载新的静态资源。一个好的解决办法是:网页中引用静态资源的路径添加应用的发布版本号,这样由于版本号的变更造成网页中静态资源路径发生更改,从而使这些静态资源成为“新的资源”。下面将版本号包含到<mvc:resources/>中。

创建版本号获取类:
import javax.servlet.ServletContext;
import org.springframework.web.context.ServletContextAware;

public class ResourcePathExposer implements ServletContextAware {
 private ServletContext servletContext;
 private String resourceRoot;

 public void init() {
  String version = "1.2.1";
  resourceRoot = "/resources-" + version;
  getServletContext().setAttribute("resourceRoot", 
    getServletContext().getContextPath()+resourceRoot);
 }

 public void setServletContext(ServletContext servletContext) {
  this.servletContext = servletContext;
 }

 public String getResourceRoot() {
  return resourceRoot;
 }

 public ServletContext getServletContext() {
  return servletContext;
 }	
}


在<mvc:resources/>中配置:
    <bean id="rpe" class="com.baobaotao.web.ResourcePathExposer"
 init-method="init"/>  
    <mvc:resources mapping="#{rpe.resourceRoot}/**" 
location="/" cache-period="31536000"/>  


在jsp中引用路径:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
  <head>
    <title>静态资源测试</title>
    <script src="${resourceRoot}/js/test.js" type="text/javascript"> </script>
  </head> 
  <body>
    hello!!
    <script>
       test(); 
    </script>
  </body>
</html>


2. 异常处理
    SpringMVC通过HandlerExceptionResolver处理程序的异常,包括处理器映射、数据绑定以及处理器执行时发生异常。
  • 大小: 268.1 KB
10
5
分享到:
评论
4 楼 chiqinghaichi 2015-05-31  
楼主好!菜鸟一枚,试了下你的程序,当访问 http://localhost/项目名/user/login.html
输入用户名和密码后提示,404错误。
3 楼 随意而生 2015-03-12  
复习复习  不错
2 楼 happy200318 2014-10-21  
给个赞,不错
1 楼 cylboke 2014-10-21  
总结的不错,赞

相关推荐

Global site tag (gtag.js) - Google Analytics