SpringMVC从入门到精通(二)
来源:互联网 发布:龙神契约披风升阶数据 编辑:程序博客网 时间:2024/05/22 12: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>
然后进行检测即可。可以用来做登录检测、性能检测等。
- SpringMVC从入门到精通(二)
- SpringMVC从入门到精通(二)
- SpringMVC从入门到精通
- springmvc从入门到精通
- SpringMVC从入门到精通(一)
- SpringMVC从入门到精通(一)
- RMS从入门到精通之二
- RMS从入门到精通之二
- Java学习从入门到精通(二)
- RMS从入门到精通之二
- VI - 从入门到精通之二
- RMS从入门到精通之二
- Servlet从入门到精通二
- Nginx开发从入门到精通二
- JMS&MQ,从入门到精通(二)
- ActiveMQ从入门到精通(二)
- Java从入门到精通(二)
- Mybatis从入门到精通 (二)
- c++编写: 检测试笔记本电池充电状况
- SpringMVC从入门到精通(一)
- 注意VC的内存使用,栈变量不可放在全局容器
- 第30章 OpenWrt实现pppoe上网
- HDU5314 Happy King
- SpringMVC从入门到精通(二)
- Java邮件发送详解
- 欧建新之死
- 页面引入jtopo后,键盘方向键事件无用解决方法
- struts2快速入门
- 又一次被绿色了
- composer 下载第三方插件库
- Unity学习 — UGUI侧滑菜单点击显示和隐藏
- spring mvc使用@InitBinder 标签对表单数据绑定