• springmvc总结2


    一、数据绑定流程(数据转化,数据格式化,数据校验)

    1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象

    2. DataBinder 调用装配在 Spring MVC 上下文中的ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中
    3. 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData 对象,错误信息写入BindResult中
    4. Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参

    二、数据转化

    默认转换器:

    用户自定义转换器:

    1、Controller:String转为User对象

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @RequestMapping("/testConversionServiceConverter")
        public String testConversionServiceConveter(@RequestParam("user") User user){
          System.out.println(user);
          return "success";
        }
      }

    Converter:

      import org.springframework.core.convert.converter.Converter;
      import org.springframework.stereotype.Component;
      import com.xxlong.domain.Address;
      import com.xxlong.domain.User;
      @Component
    
      /*Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactroyBean 中:
      *Converter<S,T>:将 S 类型对象转为 T 类型对象
      *ConverterFactory:将相同系列多个 “同质” Converter 封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将 String 转换为 Number 及 Number 子类(Integer、Long、Double   *        等)对象)可使用该转换器工厂类
      *GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换
    
      */
    
      public class StringToUserConverter implements Converter<String, User> {
        @Override
        public User convert(String source) {
          if(source!=null){
            String value[] = source.split("-");
            if(value!=null&&value.length==5){
              String username=value[0];
              String password=value[1];
              int age = Integer.parseInt(value[2]);
              Address address = new Address();
              address.setProvince(value[3]);
              address.setCity(value[4]);
              User user = new User(username,password,age,address);
              return user;
            }
          }
         return null;
        }    
      }

    dispatcherServlet-servlet.xml中添加:

      <!-- ConversionService 是 Spring 类型转换体系的核心接口.可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC容器中定义一个 ConversionService. Spring 将自动识别出IOC 容器中的     
    
      ConversionService,并在 Bean 属性配置及Spring MVC 处理方法入参绑定等场合使用它进行数据的转换 -->
    
      <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
          <list>
            <ref bean="stringToUserConverter"/>
          </list>
        </property>
      </bean>
    
      <!-- <mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的 ConversionService 注册到Spring MVC 的上下文中 -->
      <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

    view:

    请求页面index.jsp:<a href="springmvc/testConversionServiceConverter?user=xxlong-311-100-安徽-芜湖">Test ConversionServiceConverter</a>

    响应页面success.jsp:

    控制台输出:User [username=xxlong, password=311, age=100, address=Address [city=芜湖, province=安徽]] 

    三、对dataBinder的设置:

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @InitBinder
        /*由 @InitBinder 标识的方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类, 用于完成由表单字段到 JavaBean 属性的绑定
        @InitBinder方法不能有返回值,它必须声明为void。
        @InitBinder方法的参数通常是是 WebDataBinder
        */
        public void initBinder(WebDataBinder binder){
    
          //此设置可以将表单中传来的password设为null
          binder.setDisallowedFields("password");
        }
      }

      **保证map或model中没有放入key为user,value为User的对象,即不能使用@ModelAttribute中map.add("user",User)或ModelAndView中modelAndView.addObject("user",User)或         

      @SessionAttributes(value="user"),只能通过反射来创建 POJO 类型的参数, 传入为目标方法的参数(参数为表单提交的值),生成user对象的password为null

    四、数据格式化

    2、Controller:数据格式化

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @RequestMapping("/testDataFormat")
        public String testDataFormat(User user,BindingResult bindingResult){
          if(bindingResult.getErrorCount()>0){
          for(FieldError error:bindingResult.getFieldErrors()){
            System.out.println(error.getField()+":"+error.getDefaultMessage());
          }
        }
          System.out.println("user="+user);
          return "success";
        }    
      }

    User:

    /*@DateTimeFormat 注解可对java.util.Date、java.util.Calendar、java.long.Long 时间类型进行标注:
    *   pattern 属性:类型为字符串。指定解析/格式化字段数据的模式,如:”yyyy-MM-dd hh:mm:ss”
    *   iso 属性:类型为 DateTimeFormat.ISO。指定解析/格式化字段数据的ISO模式,包括四种:ISO.NONE(不使用) -- 默认、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)、

    *      ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
    *   style 属性:字符串类型。通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式:S:短日期/时间格式、M:中日期/时间格式、

    *      L:长日期/时间格式、F:完整日期/时间格式、-:忽略日期或时间格式

    */

    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birthday;

    /*@NumberFormat 可对类似数字类型的属性进行标注,它拥有两个互斥的属性:
    *    style:类型为 NumberFormat.Style。用于指定样式类型,包括三种:Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)
    *    pattern:类型为 String,自定义样式,如patter="#,###";

    */

    @NumberFormat(pattern="#,###,###.#")
    private Float salary;

    dispatchServlet-servlet.xml中添加:

      <!--对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴。
      *Spring 在格式化模块中定义了一个实现ConversionService 接口的FormattingConversionService 实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能
      *FormattingConversionService 拥有一个FormattingConversionServiceFactroyBean 工厂类,后者用于在 Spring 上下文中构造前者
    
      *FormattingConversionServiceFactroyBean 内部已经注册了 :
      *     NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用 @NumberFormat 注解
      *    JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用 @DateTimeFormat 注解
      *装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动了。
    
      -->
    
      <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
          <list>
            <ref bean="stringToUserConverter"/>
          </list>
        </property>
      </bean>
    
      <!-- <mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的 ConversionService 注册到Spring MVC 的上下文中 -->
      <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

    view:

    请求页面index.jsp:

    <form action="springmvc/testDataFormat">
    username: <input type="text" name="username"/>
    <br>
    password: <input type="password" name="password"/>
    <br>
    age: <input type="text" name="age"/>
    <br>
    birthday:<input type="text" name="birthday">
    <br>
    salary:<input type="text" name="salary">
    <br>
    city: <input type="text" name="address.city"/>
    <br>
    province: <input type="text" name="address.province"/>
    <br>
    <input type="submit" value="testDataFormat"/>
    </form>

    响应页面success.jsp:

    控制台输出:user=User [username=xxlong, password=null, age=100, birthday=Wed Mar 01 00:00:00 CST 1989, address=Address [city=wuhu, province=anhui]]

    五、数据校验

    Spring4.0拥有自己独立的数据校验框架,同时支持JSR303标准的校验框架。spring在进行数据绑定时可同时调用校验框架完成数据校验工作。

    • JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 .
    • JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对 Bean进行验证

     注解          功能说明

    @Null          被注释的元素必须为null

    @NotNull          被注释的元素必须不为null

    @AssertTrue       被注释的元素必须为true

    @AssertFalse        被注释的元素必须为false

    @Min(value)        被注释的元素必须是一个数字,其值必须大于等于指定的最小值

    @Max(value)        被注释的元素必须是一个数字,其值必须小于等于指定的最大值

    @DecimalMin(value)      被注释的元素必须是一个数字,其值必须大于等于指定的最小值

    @DecimalMax(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值

    @Size(max,min)        被注释的元素的大小必须在指定的范围内

    @Digits(integer,fraction)    被注释的元素必须是一个数字,其值必须在可接受的范围内。interger整数部分,fraction小数部分

    @Past            被注释的元素必须是一个过去的日期

    @Future              被注释的元素必须是一个将来的日期

    @Pattern(value)       被注释的元素必须符合指定的正则表达式

    Hibernate Validator扩展注解 :

    Hibernate Validator是JSR 303的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解

    注解            功能说明

    @Email            被注释的元素必须是电子邮箱地址

    @Length          被注释的字符串长度必须在指定的范围内

    @NotEmpty          被注释的字符串必须非空

    @Range          被注释的元素必须在合适的范围内 

    3、Controller:数据验证

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @RequestMapping("/testValid")
        public String testValid(@Valid User user,BindingResult bindingResult){
          if(bindingResult.getErrorCount()>0){
            for(FieldError error:bindingResult.getFieldErrors()){
            System.out.println(error.getField()+":"+error.getDefaultMessage());
          }
        }
          System.out.println("user="+user);
          return "success";
        }
      }

    User:

    @NotEmpty

    /*springMVC框架在将请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验,将校验的结果保存到随后的入参中,

    这个保存校验结果的入参必须是BindingResult或Errors类型,这两个类都位于org.springframework.validation 包中*/

    private String username;

    dispatchServlet-servlet.xml中添加:

    <!--<mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean,通过在目标方法的入参上标注 @valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作
    *Spring 的 LocalValidatorFactroyBean 既实现了 Spring 的Validator 接口,也实现了 JSR 303 的 Validator 接口。
    只要在 Spring 容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean 中。 *Spring 本身并没有提供 JSR303 的实现,所以必须将JSR303 的实现者的 jar 包放到类路径下
    --> <mvc:annotation-driven></mvc:annotation-driven>

    view:

    请求页面index.jsp:

    <form action="springmvc/testValid">
    username: <input type="text" name="username"/>
    <br>
    password: <input type="password" name="password"/>
    <br>
    age: <input type="text" name="age"/>
    <br>
    birthday:<input type="text" name="birthday">
    <br>
    salary:<input type="text" name="salary">
    <br>
    city: <input type="text" name="address.city"/>
    <br>
    province: <input type="text" name="address.province"/>
    <br>
    <input type="submit" value="testValid"/>
    </form>

    响应页面success.jsp:

    控制台输出:

    username:不能为空
    user=User [username=, password=null, age=0, birthday=null, salary=null, address=Address [city=, province=]]

    需要导入JSR验证jar包:

    classmate-0.8.0.jar
    hibernate-validator-5.0.0.CR2.jar
    hibernate-validator-annotation-processor-5.0.0.CR2.jar
    jboss-logging-3.1.1.GA.jar
    validation-api-1.1.0.CR1.jar

    4、Controller:错误信息在页面显示

     @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @RequestMapping("/testValid")
        /*@ModelAttribute("user")一定要有,不然页面不显示错误信息
        *Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,还会将所有校验结果保存到 “隐含模型”.
        *即使处理方法的签名中没有对应于表单/命令对象的结果入参,校验结果也会保存在 “隐含对象” 中。隐含模型中的所有数据最终将通过 HttpServletRequest 的
        *属性列表暴露给 JSP 视图对象,因此在 JSP 中可以获取错误信息在 JSP 页面上可通过 <form:errors path=“userName”>显示错误消息
        */
        public String testValid(@Valid @ModelAttribute("user") User user,Errors errors){
          if(errors.getErrorCount()>0){
            for(FieldError error:errors.getFieldErrors()){
              System.out.println(error.getField()+":"+error.getDefaultMessage());
            }
          return "../../index";
        }
        return "success";
      }
    }

    User:

    @NotEmpty(message="用户名不能为空")
    private String username;

    web.xml中添加:否则报错

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/dispatchServlet-servlet.xml</param-value>
    </context-param>
    
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    dispatchServlet-servlet.xml:

    <mvc:annotation-driven></mvc:annotation-driven>

    views:

    请求页面index.jsp:

    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
    //modelAttribute("user")一定要有
    
    <form:form action="springmvc/testValid" method="post" modelAttribute="user" >
    <form:errors path="*" ></form:errors><br>
    username: <input type="text" name="username"/>
    <form:errors path="username" ></form:errors>
    <br>
    password: <input type="password" name="password"/>
    <br>
    age: <input type="text" name="age"/>
    <br>
    birthday:<input type="text" name="birthday"/>
    <br>
    salary:<input type="text" name="salary"/>
    <br>
    city: <input type="text" name="address.city"/>
    <br>
    province: <input type="text" name="address.province"/>
    <br>
    <input type="submit" value="testValid"/>
    </form:form>

    响应页面index.jsp:

    用户名不能为空

    username:  用户名不能为空 

    六、错误消息国际化

    1、dispatchServlet-servlet.xml中添加:

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="xxlong_i18n"></property>
    </bean>

    2、src目录下新建

    xxlong_i18n_en_US.properties

      /*当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为前缀,结合modleAttribute、属性名及属性类型名生成多个对应的消息代码:

      *例如 User 类中的 username 属性标准了一个 @Pattern 注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4个错误代码:

      *Pattern.user.username
      *Pattern.username
      *Pattern.java.lang.String
      *Pattern

      从上往下优先级降低,优先选择Pattern.user.username,如没有,则选择Pattern.username....

      */

      NotEmpty.user.username=u56FDu9645u5316u663Eu793A_u7528u6237u540Du4E0Du80FDu4E3Au7A7AuFF01uFF01(国际化显示_用户名密码不能为空)
    xxlong_i18n_zh_CN.properties

      /*当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认的错误消息,否则使用国际化消息。*/

      NotEmpty.user.username=u56FDu9645u5316u663Eu793A_u7528u6237u540Du4E0Du80FDu4E3Au7A7AuFF01uFF01

     过程:1、数据类型转换

        2、数据类型格式化

        3、数据校验

          1)校验过程

            ①使用JSR303验证标准

              ②加入hibernate validator验证框架的jar包

            ③在SpringMVC配置文件中添加<mvc:annotation-driven/>

            ④需要在bean的属性上添加对应的注解

             ⑤在目标方法bean类型的前面添加@Valid注解

          2)验证出错转向

              需校验的Bean对象和其绑定结果对象或错误对象时成对出现的,它们之间不允许声明其他的入参  

          3)错误消息国际化    

    七、处理JSON

    HttpMessageConverter<T> 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息
    HttpMessageConverter<T>接口定义的方法:
       Boolean canRead(Class<?> clazz,MediaType mediaType): 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)
       Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。
       LIst<MediaType> getSupportMediaTypes():该转换器支持的媒体类型。
       T read(Class<? extends T> clazz,HttpInputMessage inputMessage):将请求信息流转换为 T 类型的对象。
      void write(T t,MediaType contnetType,HttpOutputMessgaeoutputMessage):将T类型的对象写到响应流中,同时指定相应的媒体类型为 contentType。

      

    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.xml.Marshaller和Unmarshaller读写XML消息

    Jaxb2RootElementHttpMessageConverter    通过JAXB2读写XML消息,将请求消息转换到标注XmlRootElement和XxmlType直接的类中

    MappingJackonHttpMessageConverter       利用Jackson开源包的ObjectMapper读写JSON数据

    RssChannelHttpMessageConverter        能够读写RSS种子消息

    AtomFeedHttpMessageConverter         和RssChannelHttpMessageConverter能够读写RSS种子消息

    DispatcherServlet默认装配了RequestMappingHandlerAdapter,而RequestMappingHandlerAdapter默认装配了如下的HttpMessageConverter:

    ByteArrayHttpMessageConverter 

    StringHttpMessageConverter

    ResourceHttpMessageConverter

    SourceHttpMessageConverter

    AllEncompassesFromHttpMessageConverter

    Jax2RootElementHttpMessageConverter

    加入jackson jar包后,又自动增加了MappingJackson2HttpMessageConverter     

    使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:
      1、使用 @RequestBody / @ResponseBody 对处理方法进行标注
      2、使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的入参或返回值
       当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时, Spring 首先根据请求头或响应头的Accept 属性选择匹配的 HttpMessageConverter, 进而根据参数类

      型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 将报错

    5、Controller: 返回json格式数据

     @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @ResponseBody
        @RequestMapping("/testJson")
        public List<User> testJson(){
          List<User> list = new ArrayList<User>();
          Address address1 = new Address("芜湖1","安徽1");
          Address address2 = new Address("芜湖2","安徽2");
          User user1 = new User("xxl1","311",100,address1);
          User user2 = new User("xxl2","312",101,address2);
          list.add(user1);
          list.add(user2);
          return list;
        }
    
      }

    views:

    请求页面index.jsp:<a href="springmvc/testJson">Test Json</a>

    返回结果:

    [{"username":"xxl1","password":"311","age":100,"birthday":null,"address":{"city":"芜湖1","province":"安徽1"}},
    {"username":"xxl2","password":"312","age":101,"birthday":null,"address":{"city":"芜湖2","province":"安徽2"}}]

     需要导入的jar包

    1、jackson-annotations-2.1.5.jar

    2、jackson-core-2.1.5.jar

    3、jackson-databind-2.1.5.jar

    6、Controller:获得请求报文中的body信息(表单是post提交)

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @ResponseBody
        @RequestMapping("/testHttpMessageConverter")
        public String testHttpMessageConverter(@RequestBody String body){
          System.out.println(body);
          return "hello"+new Date();
        }
      }

    上传的文件mongotest.text(任意类型):

    [{"name":"Tom1","age":25,"email":"basketball311@163.com","Chinese":79,"Math":60,"English":99,"Country":"USA"},
    {"name":"Tom2","age":26,"email":"basketball312@163.com","Chinese":78,"Math":61,"English":98,"Country":"China"}]

    views:

    请求页面index.jsp:

    <form action="springmvc/testHttpMessageConverter" enctype="multipart/form-data" method="post" >
    上传文件:<input type="file" name="myfile"/>    <br>
    <input type="submit" value="testHttpMessageConverter">
    </form>

    控制台输出

    ------WebKitFormBoundaryQ41xNQOLAFnb6De4
    Content-Disposition: form-data; name="myfile"; filename="mongotest"
    Content-Type: application/octet-stream

    [{"name":"Tom1","age":25,"email":"basketball311@163.com","Chinese":79,"Math":60,"English":99,"Country":"USA"},
    {"name":"Tom2","age":26,"email":"basketball312@163.com","Chinese":78,"Math":61,"English":98,"Country":"China"}]

    ------WebKitFormBoundaryQ41xNQOLAFnb6De4--

    返回结果:hello Sun Aug 16 10:51:49 CST 2015

    7、Controller:ResponseEntity<T>的使用 (文件下载)

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
        @RequestMapping("/testResponseEntity")
        public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException{
    
          //路径为WebRoot目录下,与WEB-INF同一目录下,在tomcat中为项目的根目录下
          InputStream is = session.getServletContext().getResourceAsStream("/file/mongotest.txt");
          byte[] body = new byte[is.available()];
          is.read(body);
    
          HttpHeaders headers = new HttpHeaders();
          headers.add("Content-Disposition", "attachment;filename=mongotest.txt");
    
          HttpStatus statusCode = HttpStatus.OK;
          ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body,headers, statusCode);
    
          /*//路径为项目中src目录下,在tomcat中为项目的classes目录下
          *Resource resource = new ClassPathResource("xxlong_i18n_en_US.properties");
          *byte[] body = FileCopyUtils.copyToByteArray(resource.getInputStream());
          *ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body,HttpStatus.OK);
    
          */   

          return response;
     
       }

      } 

    views:

    请求页面index.jsp:<a href="springmvc/testResponseEntity">Test ResponseEntity</a>

    返回结果:下载了mongotest.txt文件

    *在项目的WebRoot下新建一个file文件夹,并在此文件夹下新建一个mongotest.txt文件

    8、Controller:HttpEntity的使用

    @Controller
    @RequestMapping("/springmvc")
      public class Springmvc_test {
      @RequestMapping("/testHttpEntity")
      public String testHttpEntity(HttpEntity<String> entity){
        System.out.println(entity.getHeaders().getContentType());
      return "success";
      }
    }

     控制台输出:multipart/form-data;boundary=----WebKitFormBoundaryC34wSnnH975Tej58 

    八、文件上传:

    9、Controller:

    @Controller
    @RequestMapping("/springmvc")
    public class Springmvc_test {
        @RequestMapping("/testFileUpload")
      //要是单文件,则为MultipartFile
    public String testFileUpload(@RequestParam("myfile") MultipartFile[] files,HttpServletRequest request) throws IllegalStateException, IOException{ if(files!=null&&files.length>0){ for(int i=0;i<files.length;i++){ files[i].transferTo(new File("//home//xxlong//"+files[i].getOriginalFilename())); //上传到tomcat中该项目下springmvc_test/file/目录下 //files[i].transferTo(new File(request.getSession().getServletContext().getRealPath("/")+"file/"+files[i].getOriginalFilename())); } } /*InputStream is = null; OutputStream os = null; try { for(int i=0;i<files.length;i++){ is = files[i].getInputStream(); os= new FileOutputStream(new File("//home//xxlong",files[i].getOriginalFilename())); int length = 0; byte[] buffer = new byte[400]; while((length=is.read(buffer))!=-1){ os.write(buffer,0,length); } } } catch (Exception e) { e.printStackTrace(); }finally{ if(is!=null) is.close(); if(os!=null) os.close(); }*/ return "success"; } }

    dispatchServlet-servlet.xml中添加:

        <!-- Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的。
        Spring 用Jakarta Commons FileUpload 技术实现了一个MultipartResolver 实现类:CommonsMultipartResovler. 
        Spring MVC 上下文中默认没有装配 MultipartResovler,因此默认情况下不能处理文件的上传工作,如果想使用 Spring的文件上传功能,需现在上下文中配置 MultipartResolver -->
        <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- defaultEncoding: 必须和用户 JSP 的 pageEncoding 属性一致,以便正确解析表单的内容 -->
            <property name="defaultEncoding" value="UTF-8"></property>
            <!-- 上传文件最大为10M -->
            <property name="maxUploadSize"  value="10240000"></property>
        </bean>

    views:

    请求页面index.jsp:

      <form action="springmvc/testFileUpload"  enctype="multipart/form-data" method="post" >
                上传文件1:<input type="file"  name="myfile"/>    <br>
                上传文件2:<input type="file"  name="myfile"/>    <br>
                上传文件3:<input type="file"  name="myfile"/>    <br>
                <input type="submit" value="testFileUpload">
        </form>

    *为了让 CommonsMultipartResovler 正确工作,必须先将 commons-fileupload-1.2.1.jar 及 commons-io-2.0.jar的类包添加到类路径下

    九、自定义拦截器

    Interceptor:

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    public class FirstInterceptor implements HandlerInterceptor {
        @Override
        /*这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。
         * 该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器(目标方法)去进行处理,则返回true;
         * 该拦截器不需要再调用其他的拦截器或目标方法去处理请求,则返回false。
         * 可以用作事务,日志
         * */
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                Object handler) throws Exception {
            System.out.println("FirstInterceptor:preHandle");
            return true;
        }
        /*这个方法在业务处理器处理完请求后,但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求request的属性和视图进行处理。*/
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse request,
                Object response, ModelAndView modelAndView) throws Exception {
            System.out.println("FirstInterceptor:postHandle");
    
        }
        /*这个方法在 DispatcherServlet 完全处理完请求后被调用(渲染视图render),可以在该方法中进行一些资源清理的操作*/
        @Override
        public void afterCompletion(HttpServletRequest request,
                HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            System.out.println("FirstInterceptor:afterCompletion");
        }
    }

    dispatchServlet-servlet.xml:

            <mvc:interceptor>
                    <!-- 拦截所有请求 -->
                    <mvc:mapping path="/**"/>
                    
                    <!-- 只拦截/springmvc/testRequestMapping路径的请求 
                    <mvc:mapping path="/springmvc/testRequestMapping"/>-->
                    
                    <!-- 不拦截/springmvc/testRequestMapping的请求 -->
                    <mvc:exclude-mapping path="/springmvc/testRequestMapping" />
                    <bean class="com.xxlong.interceptors.FirstInterceptor"></bean>
            </mvc:interceptor>

    流程图:

    十、异常处理:

    Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射数据绑定以及目标方法执行时发生的异常。
    SpringMVC 提供的 HandlerExceptionResolver 的实现类:

    1、ExceptionHandlerExceptionResolver

    2、AnnotationMethodHandlerExceptionResolver

    3、DefaultHandlerExceptionResolver

    4、ResponseStatusExceptionResolver

    5、SimpleMappingExceptionResolver

    DispatchServlet默认装配的HandlerExceptionResolver:

    --没有使用<mvc:annotation-driver/>配置:

      1、AnnotationMethodHandlerExceptionResolver(已过时)  

      2、ResponseStatusExceptionResolver

      3、DefaultHandlerExceptionResolver

    --使用了<mvc:annotation-driven/>配置:

      1、ExceptionHandlerExceptionResolver

      2、ResponseStatusExceptionResolver  

      3、DefaultHandlerExctptionResolver      

     

    1、ExceptionHandlerExceptionResolver

    10、Controller:

      @Controller
      @RequestMapping("/springmvc")
      public class Springmvc_test {
          @RequestMapping("/testExceptionHandlerResolver")
          public String testExceptionHandlerResolver(@RequestParam("i") int i){
              System.out.println(10/i);
              return "success";
          }

    /* * 1、@ExceptionHandler注解的入参可以是异常Exception数组 * 2、@ExceptionHandler注解修饰的方法(handlerArithmeticException)的入参是Exception对象 * 3、@ExceptionHandler注解修饰的方法(handlerArithmeticException)的入参不能是map对象, 要想把错误信息传到页面上,需要使用ModelAndView作为返回值 * 4、@ExceptionHandler注解的优先级@Controller注解修饰的类中的@ExceptionHandler修饰方法优先级高于@ControllerAdvice注解修饰的类中的@ExceptionHandler修饰方法 * 在同一个注解下的ArithmeticException优先级高于RuntimeException(根据异常的最近继承关系,继承深度越浅的那个优先级越高) * */@ExceptionHandler({ArithmeticException.class})
    public ModelAndView handlerArithmeticException(Exception ex){
            System.out.println("[出错了:ArithmeticException]"+ex);
            ModelAndView modelAndView = new ModelAndView("error");
            modelAndView.addObject("xxlong_exception", ex);
    return modelAndView;
        }
        
        @ExceptionHandler({RuntimeException.class})
        public ModelAndView handlerRuntimeException(Exception ex){
            System.out.println("[出错了:RuntimeException]"+ex);
            ModelAndView modelAndView = new ModelAndView("error");
            modelAndView.addObject("xxlong_exception", ex);
            return modelAndView;
        }

    com.xxlong.exceptionhandler包下新建:

    @ControllerAdvice
    public class MyExceptionHandler {
        @ExceptionHandler({ArithmeticException.class})
        public ModelAndView handlerRuntimeException(Exception ex){
            System.out.println("[出错了:ControllerAdvice ArithmeticException]"+ex);
            ModelAndView modelAndView = new ModelAndView("error");
            modelAndView.addObject("xxlong_exception", ex);
            return modelAndView;
        }
    }

    views:

    请求页面index.jsp:<a href="springmvc/testExceptionHandlerResolver?i=0">Test ExceptionHandlerResolver</a>

    响应页面error.jsp:${xxlong_exception}   ${requestScope.xxlong_exception }

    控制台输出:

    FirstInterceptor:preHandle
    [出错了:ArithmeticException]java.lang.ArithmeticException: / by zero
    FirstInterceptor:afterCompletion

    页面输出:

    java.lang.ArithmeticException: / by zero
    java.lang.ArithmeticException: / by zero

    2、 ResponseStatusExceptionResolver

    在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
    定义一个 @ResponseStatus 注解修饰的异常类

    11、Controller

    @Controller
    @RequestMapping("/springmvc")
    public class Springmvc_test {
        @RequestMapping("/testResponseStatusHandlerResolver")
        public String testExceptionHandlerResolver(@RequestParam("i") int i){
            if(i==10){
                throw new MyArithmeticException();
            }        
            return "success";
        }
    }

    com.xxlong.exceptionhandler包下新建:

    @ResponseStatus(value=HttpStatus.FORBIDDEN,reason="输入值不能为10!")
    public class MyArithmeticException extends RuntimeException {
    
    }

    views:

    请求页面index.jsp:<a href="springmvc/testResponseStatusHandlerResolver?i=10">Test ResponseStatusHandlerResolver</a>

    返回结果:

    @ResponseStatus也可用在目标方法上

    @Controller
    @RequestMapping("/springmvc")
    public class Springmvc_test {
        @ResponseStatus(value=HttpStatus.NOT_FOUND,reason="资源找不到")
        @RequestMapping("/testExceptionHandlerResolver")
        public String testExceptionHandlerResolver(@RequestParam("i") int i){
            if(i==10){
                throw new MyArithmeticException();
            }        
            return "success";
        }
    }

    views:

    请求页面index.jsp:<a href="springmvc/testResponseStatusHandlerResolver?i=10">Test ResponseStatusHandlerResolver</a>        还是上图结果

    <a href="springmvc/testResponseStatusHandlerResolver?i=11">Test ResponseStatusHandlerResolver</a>

    响应结果:

    3、DefaultHandlerExceptionResolver

    对一些特殊的异常进行处理,比如

      NoSuchRequestHandlingMethodException

      HttpRequestMethodNotSupportedException

      HttpMediaTypeNotSupportedException

      HttpMediaTypeNotAcceptableException

    4、SimpleMappingExceptionResolver

    dispatchServlet-servlet.xml中添加:

        <!-- 对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常,优先级比ExceptionHandlerExceptionResolver的优先级要低,即优先找@ExceptionHandler(包括@Controller和@ControllerAdvice修饰的类)注解的方法,如果没有则再使用这个-->
        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <!-- 设置异常名,这样在error.jsp中使用${requestScope.xxlong_exception}。如果不设置,则默认名称为exception,error.jsp中使用${requestScope.exception} -->
            <property name="exceptionAttribute" value="xxlong_exception"></property>
            <property name="exceptionMappings">
                <props>
                    <prop key="java.lang.ArithmeticException">error</prop>
                    <prop key=" java.lang.ArrayIndexOutOfBoundsException">error2</prop>
                </props>
            </property>

     *由于不是DispatchServlet默认装配的HandlerExceptionResolver,所以要在dispatchServlet-servlet.xml中配置

    十一、springmvc运行流程

    十二、springmvc自动扫描包

        <!-- 配置自定扫描的包 -->
        <context:component-scan base-package="com.xxlong" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--  <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> -->
        </context:component-scan>

    十三、springmvc与struts的对比

    1、Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
    2、Spring MVC 会稍微比 Struts2 快些. Spring MVC 是基于方法设计, 而 Sturts2 是基于类, 每次发一次请求都会实例一个 Action.
    3、Spring MVC 使用更加简洁, 开发效率Spring MVC确实比 struts2 高: 支持 JSR303, 处理 ajax 的请求更方便
    4、Struts2 的 OGNL 表达式使页面的开发效率相比Spring MVC 更高些.

  • 相关阅读:
    org.dom4j.DocumentException: null Nested exception: null
    严重: 文档无效: 找不到语法。 at (null:2:19)
    微信 群好友 的返回微信号 有阉割
    Perl 面向对象的真正意思
    门外汉怎么成就咨询大单(1)——北漂18年(39)
    Perl 微信模块--Weixin::Client
    Solr使用入门指南
    Perl 对象是函数的第一个参数
    haproxy 4层负载
    mysql 从读负载
  • 原文地址:https://www.cnblogs.com/xxlong/p/4727666.html
Copyright © 2020-2023  润新知