Spring MVC 实践 - Component
Spring MVC 实践
标签 : Java与Web
Converter
Spring MVC的数据绑定并非没有任何限制, 有案例表明: Spring在如何正确绑定数据方面是杂乱无章的. 比如: Spring总是试图用默认的语言区域将日期输入绑定到
java.util.Data
, 如果想要使用不同的日期格式(format),就需要Converter
的协助.
Spring提供了Converter
接口来供开发者自定义Converter
类:
/*** @since 3.0* @param <S> the source type* @param <T> the target type*/
public interface Converter<S, T> {T convert(S source);
}
- 自定义
Converter
:
/*** @author jifang.* @since 2016/6/19 7:23.*/
public class StringDateConverter implements Converter<String, Date> {private String pattern;public StringDateConverter(String pattern) {this.pattern = pattern;}@Overridepublic Date convert(String source) {try {return new SimpleDateFormat(pattern).parse(source);} catch (ParseException e) {throw new RuntimeException(e);}}
}
- 配置
为了能够让Spring MVC使用我们自定义的Converter
, 需要在配置文件中配置一个ConversionServiceFactoryBean
:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><set><bean class="com.fq.mvc.converter.StringDateConverter"><constructor-arg type="java.lang.String" value="yyyy-MM-dd hh:mm:ss"/></bean></set></property>
</bean>
然后为<annotation-driven/>
配置conversion-service
属性:
<mvc:annotation-driven conversion-service="conversionService"/>
注: 还可以使用
FormattingConversionServiceFactoryBean
来加载Converter
, 由于其配置方法与ConversionServiceFactoryBean
, 故在此就不再赘述.
Controller
@RequestMapping("/add_user.do")
public String addUser(User user, BindingResult binding) {if (binding.hasErrors()) {FieldError error = binding.getFieldError();// log ...}service.addUser(user);return "redirect: users.do";
}
BindingResult
参数中放置了Spring的所有绑定错误.
Interceptor
Spring MVC的拦截器类似于Servlet中的
Filter
(关于Filter
,详细可参考Servlet - Listener、Filter、Decorator),用于Controller
进行预处理和后处理.
Spring提供了Interceptor
接口来供开发者自定义Interceptor
类:
public interface HandlerInterceptor {/*** 进入Controller方法前执行* 应用场景: 身份认证、身份授权等*/boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;/*** 进入Controller方法后, 返回ModelAndView前执行* 应用场景: 将公共模型数据填充到ModelAndView、统一指定视图等*/void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;/*** 执行完Controller方法后执行* 应用场景: 统一日志处理、统一异常处理等*/void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;}
示例: 统计Controller执行耗时.
- 自定义
Interceptor
/*** @author jifang* @since 16/7/4 上午10:35.*/
public class HandleTimeInterceptor implements HandlerInterceptor {private static final String START_TIME = "start_time";private static final String HANDLE_TIME = "handle_time";private static final Logger LOGGER = LoggerFactory.getLogger(HandleTimeInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {request.setAttribute(START_TIME, System.currentTimeMillis());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {long start = (long) request.getAttribute(START_TIME);request.setAttribute(HANDLE_TIME, System.currentTimeMillis() - start);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {String uri = request.getRequestURI();long consume = (long) request.getAttribute(HANDLE_TIME);LOGGER.info("uri: {} consume {}s", uri, consume / 1000);}
}
- 配置
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.fq.mvc.interceptor.HandleTimeInterceptor"/></mvc:interceptor>
</mvc:interceptors>
Upload
Spring MVC提供了对Servlet 3.0文件上传的支持(关于Servlet 3.0文件上传可参考博客Servlet - Upload、Download、Async、动态注册).
Spring MVC提供了MultipartFile
接口,上传到应用中的文件都被包装在一个MultipartFile
对象中:
MultipartFile
|
描述 |
---|---|
String getName()
|
Return the name of the parameter in the multipart form. |
String getOriginalFilename()
|
Return the original filename in the client’s filesystem. |
long getSize()
|
Return the size of the file in bytes. |
boolean isEmpty()
|
Return whether the uploaded file is empty, that is, either no file has been chosen in the multipart form or the chosen file has no content. |
String getContentType()
|
Return the content type of the file. |
byte[] getBytes()
|
Return the contents of the file as an array of bytes. |
InputStream getInputStream()
|
Return an InputStream to read the contents of the file from. |
void transferTo(File dest)
|
Transfer the received file to the given destination file. |
在Servlet 3.0及更高版本的容器中进行文件上传编程,总是围绕着@MultipartConfig
注解和Part
接口,处理上传文件的Servlet必须以@MultipartConfig
注解标注, 但DispatcherServlet
是Spring jar包已经编译好的类, 无法进行修改,值得庆幸的是Servlet 3.0还可以使用部署描述符web.xml将一个Servlet变为MultipartConfig Servlet:
<servlet><servlet-name>mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/mvc-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup><multipart-config><max-file-size>20848820</max-file-size><file-size-threshold>1048576</file-size-threshold></multipart-config>
</servlet>
<servlet-mapping><servlet-name>mvc</servlet-name><url-pattern>*.do</url-pattern>
</servlet-mapping>
此外, 在mvc-servlet.xml文件中配置一个MultipartResolver:
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
此时就可以进行文件上传编程了:
@RequestMapping("/upload.do")
public String upload(MultipartFile file) throws IOException {String name = file.getOriginalFilename();String fileName = String.format("/data/file/%s", name);file.transferTo(new File(fileName));return "file_upload";
}
Exception
系统异常包含两类: 预期异常、运行时异常
RuntimeException
.前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生.
基于Spring MVC的DAO
、Service
、Controller
的异常都可以通过throw
向上层抛出,最后统一由DispatcherServlet
的异常处理器进行处理.
- 自定义异常
如果Controller
/Service
/DAO
抛出此类异常说明是预期异常:
/*** @author jifang.* @since 2016/6/21 16:28.*/
public class MVCException extends Exception {private String message;public MVCException(String message) {super(message);this.message = message;}@Overridepublic String getMessage() {return this.message;}public void setMessage(String message) {this.message = message;}
}
- 异常处理器
/*** @author jifang.* @since 2016/6/21 16:33.*/
public class MVCExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {String message;if (ex instanceof MVCException) {message = ex.getMessage();} else {message = "未知异常";}return new ModelAndView("error", "message", message);}
}
- error.vm
<html>
<head><title>错误信息</title><meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
</head>
<body>
${message}
</body>
</html>
- 注册异常处理器
<bean class="com.fq.mvc.exception.MVCExceptionResolver"/>
JSON
JSON数据格式形式简单, 解析方便, 因此常用在接口调用、HTML页面中.
Spring MVC对其提供了如下支持:在Controller
方法上添加@ResponseBody
注解, Spring MVC会自动将Java对象转换成JSON字符串输出; 在方法形参上添加@RequestBody
注解, Spring MVC会自动将JSON串转换成Java对象:
@ResponseBody
@RequestMapping("/user_json.do")
public User userJSON(@RequestBody User user) {return user;
}
- fastjson
Spring MVC默认使用jackson对request
/response
进行JSON转换,而在此我们选用性能更高的fastjson, 因此需要在<annotation-driven/>
中另做配置.
首先, 使用fastjson需要在pom.xml中添加如下依赖:
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.7</version>
</dependency>
然后在mvc-servlet.xml中做如下配置:
<mvc:annotation-driven><mvc:message-converters register-defaults="false"><bean id="fastJsonHttpMessageConverter"class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/html;charset=UTF-8</value><value>application/json;charset=UTF-8</value></list></property><property name="features"><array value-type="com.alibaba.fastjson.serializer.SerializerFeature"><value>DisableCircularReferenceDetect</value></array></property></bean></mvc:message-converters>
</mvc:annotation-driven>
Other
1. POST Encoder
在web.xml配置一个编码Filter
可以解决POST乱码问题:
<filter><filter-name>encodingFilter</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><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
2. GET Encoder
对于GET乱码, 由于Tomcat 8.0之前版本默认使用ISO-8859-1
编码, 因此有两种解决方案:
- 修改tomcat配置文件
修改tomcat配置文件server.xml设置编码与工程编码一致:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- 重新编码
将经Tomcat编码的内容解码后再重新编码为UTF-8:
String name = new String(request.getParamter("name").getBytes("ISO8859-1"),"utf-8");
注: Tomcat 8.0及更高版本的容器不用此配置.
3. Static Resources Mapping
如果将DispatherServlet
配置成拦截所有请求<url-pattern>/</url-pattern>
, 则必须额外配置静态资源的映射规则, 否则Spring MVC会对像js/css之类的文件也做转发.
Spring MVC使用<mvc:resources/>
元素配置对静态资源的映射:
<mvc:resources location="/js/" mapping="/js/**"/>
Spring MVC 实践 - Component相关推荐
- Spring MVC 实践 - Base
Spring MVC 实践 标签 : Java与Web Spring Web MVC Spring-Web-MVC是一种基于请求驱动的轻量级Web-MVC设计模式框架, Spring MVC使用MVC ...
- Spring MVC 实践笔记
1.了解 Maven 的用法:http://spring.io/guides/gs/maven/ .这篇英文非常详细的演示了 Maven 的用法,在命令行下执行.注意,运行Maven的时候,Maven ...
- 搭建Spring4+Spring MVC web工程的最佳实践
Spring是个非常非常非常优秀的java框架,主要是用它的IOC容器帮我们依赖注入和管理一些程序中的Bean组件,实现低耦合关联,最终提高系统可扩展性和可维护性,用它来辅助我们构建web工程将 ...
- JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践
任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用在很多时候,同样的数据验证逻辑会出现在不同的层, ...
- spring mvc xss html,note/SpringMvc防御XSS实践.md at master · yangc91/note · GitHub
SpringMvc防御XSS实践 项目在漏洞扫描时发现xss漏洞, 本以为是常见漏洞,网上有很多解决方案,应该能很快搞定,但实际上文章看了不少,却并未找到十分"顺手"的解决方案. ...
- springboot templates读取不到_整合spring mvc + mybatis,其实很简单,spring boot实践(5)
01 spring boot读取配置信息 02 多环境配置 03 处理全局异常 04 spring boot admin 主要通过spring boot整合spring mvc 以及mybatis实现 ...
- 看透 Spring MVC 源代码分析与实践 —— 俯视 Spring MVC
Spring MVC Spring MVC 之初体验 环境搭建 在 IDEA 中新建一个 web 项目,用 Maven 管理项目的话,在 pom.xml 中加入 Spring MVC 和 Servle ...
- Spring MVC与JAX-RS比较与分析
http://www.infoq.com/cn/articles/springmvc_jsx-rs 过去几年,REST逐渐成为影响Web框架.Web协议与Web应用设计的重要概念.如果你还不了解RES ...
- 在Spring MVC中使用Apache Shiro安全框架
我们在这里将对一个集成了Spring MVC+Hibernate+Apache Shiro的项目进行了一个简单说明.这个项目将展示如何在Spring MVC 中使用Apache Shiro来构建我们的 ...
最新文章
- 20210709未来智能实验室收录资料
- Autolisp:利用AuoCAD之Lisp编程案例之自动智能获取所选对象的面积并标注在指定位置
- WEB API 系列(二) Filter的使用以及执行顺序
- interface not supported怎么解决_这20个婚礼伴手礼,怎么看都比喜糖有创意!
- 蒙特卡洛算法_MCMC、蒙特卡洛近似和Metropolis算法简介
- MJRefresh自定义刷新动画
- 计算机处理问题的数学模型分为哪两类,数据模型与决策习题与参考答案
- 突破Dr.com校园网客户端对于热点和路由器的限制
- HTTP/HTTPS/SOCKS5协议的区别
- 小米笔记本Air13.3加装固态硬盘
- 来自android的大文件清理,还在一键清理手机垃圾教你删除这些空文件夹,释放超大内存...
- Android打地鼠小游戏案例
- android企业自定义桌面
- 一次聚类引发的一系列问题(多线程篇-多线程慢于单线程)
- 男童跌入水渠被冲出千米 不会游泳女子将其救起
- JS 基础篇(音量调节器)
- word排版案例报告_导师:论文排版都搞不好,你拿什么去投稿?!
- SaliencyReview:显著性检测综述阅读笔记
- 从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序
- 编辑为什么建议转投_SCI编辑建议转投容易录用吗
热门文章
- 计算机网络之物理层:7、物理层设备(中继器、集线器)
- (王道408考研操作系统)第二章进程管理-第一节5:线程概念和多线程模型
- (王道408考研操作系统)第二章进程管理-第一节1:进程、PCB及其特征
- python numpy中数组.min()
- 处理大并发之四 libevent demo详细分析(对比epoll)
- shell判断数组内是否包含某成员,获取数组长度
- C/C++:Windows编程—Windows RPC 传递自定义数据类型、自定义数据类型数组、指针数组
- 数据结构与算法:企业级链表实现(超详细)
- 构造函数失败_抛出异常
- JavaEE实战班第18天