SpringMVC从入门到精通(二)

来源:互联网 发布:mac怎么下载r语言 编辑:程序博客网 时间:2024/05/23 02:00

Spring MVC

Spring MVC数据类型转换

Spring3引入了更加通用的类型转换系统,其定义了SPI接口(Converter等)和相应的运行时执行类型转换的API(ConversionService等)。该类型转换系统是Spring通用的,其定义在org.springframework.core.convert包中,提供无状态、强类型且可以在任意类型之间转换的类型转换系统,可以用于任何需要的地方,如SpEL、数据绑定。

类型转换器有如下三种接口

(1 )、Converter:类型转换器,用于转换S类型到T类型,此接口的实现必须是线程安全的且可以被共享。

    package org.springframework.core.convert.converter;      public interface Converter<S, T> { //① S是源类型 T是目标类型          T convert(S source); //② 转换S类型的source到T目标类型的转换方法      }   Converter接口实现只能转换一种类型到另一种类型,不能进行多类型转换,如将一个数组转换成集合,如(String[] ----> List<String>、String[]----->List<PhoneNumberModel>等)

(2 )、GenericConverter和ConditionalGenericConverter:GenericConverter接口实现能在多种类型之间进行转换,ConditionalGenericConverter是有条件的在多种类型之间进行转换。

    package org.springframework.core.convert.converter;      public interface GenericConverter {          //getConvertibleTypes:指定了可以转换的目标类型对;        Set<ConvertiblePair> getConvertibleTypes();           //convert:在sourceType和targetType类型之间进行转换        Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);      } 
package org.springframework.core.convert.converter;  public interface ConditionalGenericConverter extends GenericConverter {      //matches:用于判断sourceType和targetType类型之间能否进行类型转换    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);  }   对于我们大部分用户来说一般不需要自定义GenericConverter, 如果需要可以参考内置的GenericConverter来实现类型转换。

(3 )、ConverterFactory:工厂模式的实现,用于选择将一种S源类型转换为R类型的子类型T的转换器的工厂接口。

    package org.springframework.core.convert.converter;      public interface ConverterFactory<S, R> {          <T extends R> Converter<S, T> getConverter(Class<T> targetType);      }       S:源类型;R目标类型的父类型;T:目标类型,且是R类型的子类型;    getConverter:得到目标类型的对应的转换器。    如org.springframework.core.convert.support.NumberToNumberConverterFactory用于在Number类型子类型之间进行转换,如Integer--->Double, Byte---->Integer, Float--->Double等。     对于我们大部分用户来说一般不需要自定义ConverterFactory,如果需要可以参考内置的ConverterFactory来实现类型转换。

类型转换器注册器、类型转换服务有如下两种接口

类型转换器注册器、类型转换服务:提供类型转换器注册支持,运行时类型转换API支持。

(1 )、ConverterRegistry:类型转换器注册支持,可以注册/删除相应的类型转换器

    public interface ConverterRegistry {          void addConverter(Converter<?, ?> converter);          void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter);          void addConverter(GenericConverter converter);          void addConverterFactory(ConverterFactory<?, ?> converterFactory);          void removeConvertible(Class<?> sourceType, Class<?> targetType);      }     可以注册:Converter实现,GenericConverter实现,ConverterFactory实现。

(2 )、ConversionService:运行时类型转换服务接口,提供运行期类型转换的支持。

    package org.springframework.core.convert;      public interface ConversionService {          boolean canConvert(Class<?> sourceType, Class<?> targetType);          boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);          <T> T convert(Object source, Class<T> targetType);          Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);      }      convert:将源对象转换为目标类型的目标对象。  Spring提供了两个默认实现(其都实现了ConverterRegistry、ConversionService接口):DefaultConversionService:默认的类型转换服务实现;DefaultFormattingConversionService:带数据格式化支持的类型转换服务实现,一般使用该服务实现即可。

Spring内建的类型转换器

这里写图片描述

这里写图片描述

自定义类型转换

我们将页面传递的字符串转换为标准化日期格式。

1.先实现类型转换器 public class DateConverter implements Converter<String, Date> {     //将传入的字符串转换为日期    public Date convert(String source) {        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        try {            Date date = format.parse(source);            return date;        } catch (ParseException e) {            e.printStackTrace();        }        return null;    }}
2.在springmvc配置文件中注册ConversionService实现和自定义的类型转换器 <bean  id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">    <!--可以自定义很多类型转换器-->    <property name="converters">        <list>            <bean class="cn.cad.converter.DateConverter"></bean>        </list>    </property></bean>FormattingConversionServiceFactoryBean:是FactoryBean实现,默认使用DefaultFormattingConversionService转换器服务实现;
3.通过ConfigurableWebBindingInitializer注册ConversionService <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">    <property name="conversionService" ref="conversionService"/></bean>
4.注册ConfigurableWebBindingInitializer到RequestMappingHandlerAdapte <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">    <property name="webBindingInitializer" ref="customBinder"></property></bean> 

上面的方法看起来太过繁琐,SpringMVC提供了如下更简单的配置。

<!--前面说过使用<mvc:annotation-driven>就不用再配置映射器和适配器--><mvc:annotation-driven conversion-service="conversionService" /><bean  id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">    <property name="converters">        <list>            <bean class="cn.cad.converter.DateConverter"></bean>        </list>    </property></bean>

如上就完成了类型转换,我们程序页面输入的日期一定要符合format的格式,才能完成转换,否则就会出异常。

Controller返回类型

ModelAndView

controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。  

void

有的时候我们并不需要返回值,例如ajax请求时。不过我们也可以在方法参数列表上添加request等来进行页面跳转等操作。 

String

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。 至于数据,我们可以通过默认的Model或者ModelMap来传递参数。通过 return "redirect:/xxx.jso"  来重定向或者转发

SpringMVC异常处理

在SpringMVC中,系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

这里写图片描述

这里有篇关于SpringMVC异常处理的文章写的很棒,我就不再重复。
http://blog.csdn.net/eson_15/article/details/51731567

SpringMVC文件上传

1.首先需要加入jar包

这里写图片描述

2.配置上传解析器<bean id="multipartResolver"    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    <!-- 设置文件上传大小 -->    <property name="maxUploadSize" value="5000000" /></bean>
3.表单一定要设置enctype="multipart/form-data" 然后接收文件的方法 添加一个参数 //通过MultipartFile 接收上传的文件public  ModelAndView updateItem(Items item,MultipartFile pictureFile) throws IllegalStateException, Exception {        String picName = UUID.randomUUID().toString();        // 获取文件名        String oriName = pictureFile.getOriginalFilename();        System.out.println(oriName);        // 开始上传文件        pictureFile.transferTo(new File("F:\\upload\\" + picName + extName));        itemService.updateItemById(item);        ModelAndView modelAndView=new ModelAndView();        modelAndView.setViewName("forward:/itemEdit");        return modelAndView;    }

这篇博客详细介绍了SpringMVC的上传下载。
http://blog.csdn.net/evankaka/article/details/45826697/

SpringMVC拦截器

Spring Web MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

拦截器接口

package org.springframework.web.servlet;  public interface HandlerInterceptor {      boolean preHandle(              HttpServletRequest request, HttpServletResponse response,               Object handler)               throws Exception;      void postHandle(              HttpServletRequest request, HttpServletResponse response,               Object handler, ModelAndView modelAndView)               throws Exception;      void afterCompletion(              HttpServletRequest request, HttpServletResponse response,               Object handler, Exception ex)              throws Exception;  }  
preHandle:处理器前执行的方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);     返回值:true表示继续流程(如调用下一个拦截器或处理器);           false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应; postHandle:处理器后回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。 afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。 

有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器,允许我们只实现需要的回调方法。

public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {       //省略代码 此处所以三个回调方法都是空实现,preHandle返回true。  }  

案例

1.编写拦截器public class HandlerInterceptor1 extends HandlerInterceptorAdapter {//此处一般继承HandlerInterceptorAdapter适配器即可      @Override      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {          System.out.println("===========拦截器 preHandle");          return true;      }      @Override      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {          System.out.println("===========拦截器 postHandle");      }      @Override      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {          System.out.println("===========拦截器 afterCompletion");      }
2.编写处理器@Controllerpublic class TestController {      @RequestMapping("/test")    public ModelAndView test() {          System.out.println("===========TestController");          return new ModelAndView("test");      }  }  
3.配置拦截器<mvc:interceptors>    <!--可以配置很多拦截器-->    <mvc:interceptor>        <!-- 所有的请求都进入拦截器 -->        <mvc:mapping path="/**" />        <!-- 配置具体的拦截器 -->        <bean class="cn.cad.HandlerInterceptor1" />    </mvc:interceptor></mvc:interceptors>

然后进行检测即可。可以用来做登录检测、性能检测等。

原创粉丝点击