springmvc拦截器原理 mvc假设每次请求controller都封装一个pojo

Spring mvc中把表单数据当做一个对象提交给controller是怎么实现的? - ITeye问答
Spring mvc中把表单数据当做一个对象提交给controller是怎么实现的?对应spring源码在哪里写的?
&&&&&&& @RequestMapping("save")
public Object save(Person person){
Person p = personService.save(person);
不知道楼主搞定了木有,
SpringMVC 可以使用命令表单对象来自动设置值的。
只要你input里面的name的值和 你实体里面的值是一样的,
然后再Controller上面定义一个user对象,
就可以获取到了。
通常会用楼主的方法,特殊情况下,自己会动手写一个。
protected &T& T getParamByBean(HttpServletRequest request, Class&T& clazz) {
bean = clazz.newInstance();
} catch (InstantiationException e) {
log.debug(e.getMessage());
} catch (IllegalAccessException e) {
log.debug(e.getMessage());
Enumeration&String& enums = request.getParameterNames();
while (enums.hasMoreElements()) {
String key = enums.nextElement();
String val = request.getParameter(key);
if (!BaseUtils.isEmpty(val))
ReflectUtils.setFieldValueIgnoreCase(bean, key, val);
这是简单版spring源码了。
HttpMessageConverter
本座的一篇博文开解您心中愁绪:
《深度剖析:Java POJO Bean 对象与 Web Form 表单的自动装配》:
可参考数据绑定
已解决问题
未解决问题springMVC笔记系列(11)——使用 POJO 对象绑定请求参数值
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。如:dept.deptId、dept.address.tel 等
说的通俗点就是,平时我们想将请求页面的表单数据接收并封装成特定对象的时候,少不了做的是在某个servlet的对应方法中从request中将各个表单参数取出,类型转换好,构造一个特定类型的对象,再把表单参数都存进去。
如果表单的项目很多,想想那些在线简历、考试报名等表单吧,你发现你的技术活完全成了体力活。springMVC除了能够按照请求的方法、头、url及参数进行映射外,还能够使用 POJO 对象绑定请求参数值。只要你能保证请求页面的表单输入项的name与POJO对象类的域名称相同即可。
另外,springMVC的该功能还支持级联属性,也就是支持POJO中的域是另一个POJO对象的情况。相应地,表单的name写为:pojo1的域名.pojo2的域名
具体还是看例子吧。现在有个Person类:
package com.happyBKs.springmvc.
public class Person {
public String getUsername() {
public void setUsername(String username) {
this.username =
public int getAge() {
public void setAge(int age) {
this.age =
public Location getLocal() {
public void setLocal(Location local) {
this.local =
public String toString() {
return "Person [username=" + username + ", age=" + age + ", local="
+ local + "]";
注意到了吗,其中的一个属性是Location类的,即local包含级联属性。Location类如下:
package com.happyBKs.springmvc.
public class Location {
public String getCity() {
public void setCity(String city) {
this.city =
public String getProvince() {
public void setProvince(String province) {
this.province =
public String toString() {
return "Location [city=" + city + ", province=" + province + "]";
控制器类如下:
package com.happyBKs.springmvc.handlers
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import com.happyBKs.springmvc.beans.Person
@RequestMapping("/class")
@Controller
public class POJORequestHandler {
String page="successrm"
@RequestMapping("/boy")
public String handle(Person stud)
System.out.println(stud.toString())
return page
请求页面如下:
&%@ page language="java" contentType="text/ charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%&
&!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&
http-equiv="Content-Type" content="text/ charset=ISO-8859-1"&
&Insert title here&
action="class/boy" method="post"&
username: type="text" name="username"/&
age: type="text" name="age"/&
city: type="text" name="local.city"/&
province: type="text" name="local.province"/&
type="submit" value="GO"/&
运行过程:
控制台输出:
Person [username=happBKs, age=2, local=Location [city=urban, province=Shanghai]]
如果请求的表单参数中不存在pojo对象中的某个域名称的项目,则绑定后pojo该属性为null。
如果请求的表单参数中存在pojo对象中没有包含的域的项目,则绑定后该参数丢失。
如果表单项目的数据会自动从String转换为相应pojo的域类型。但如果类型无法转换,则报错。
如我输入age为dafsdfa,那么报错。
Spring MVC学习---JSON转换功能(启动Spring MVC的注解功能,完成请求和注解POJO的映射)
关于springmvc pojo参数绑定“不成功”的一个原因
SpringMVC 开发过程问题总结-, 实体关系映射对象属性要用包装类Integer, Long ,Double
SpringMVC映射请求参数的方式(参数绑定方式)
SpringMVC对象绑定时自定义名称对应关系
Springmvc接受不同对象的同名参数解决方法:
spring-mvc jsp表单提交 不同POJO的相同属性[同名参数]
Spring mvc中把表单数据当做一个对象提交给controller的实现
没有更多推荐了,项目组用了 Spring MVC 进行开发,觉得对里面的使用方式不是很满意,就想,如果是我来搭建开发环境,我会怎么做?下面就是我的想法,只关注于 MVC 的 View 层。
一、统一的响应格式
现在基本上都是用 ajax 来调用后台接口,拿到 json格式的数据再展示,有的人直接返回数据,却没有考虑异常的情况,我觉得返回的报文里必须包含表示可能的异常信息的数据和业务响应数据。我定义了下面这个类来表示报文格式:
* 统一的 HTTP 响应格式。&br/&
* code 为 &ok& 表示业务调用成功,否则是失败的错误码,如果有多个则以逗号分隔。&br/&
* data 是业务数据,如果失败了则是 null。
* @author http://coderbee.net
public class RespBody {
public static final String OK_CODE = &ok&;
private final S
private final O
private static final RespBody OK = new RespBody(OK_CODE, null);
private RespBody(String code, Object data) {
this.code =
this.data =
public static RespBody ok() {
return OK;
public static RespBody ok(Object data) {
return new RespBody(&ok&, data);
public static RespBody error(String code) {
return new RespBody(code, null);
public static RespBody error(String code, Object msg) {
return new RespBody(code, msg);
public String getCode() {
public Object getData() {
这个类提供了一些静态方法来快速构建响应报文,这也是很重要的一个设计:用静态工厂方法而不是构造函数。
code 不应该是直接的错误提示信息,应该只是简单的错误编码,这样不同的客户端都可以调用这个 API,然后再根据错误编码、客户端语言和自己的客户端特性选择合适的错误提示信息和提示方式。
二、统一的异常处理
很多人都不考虑异常的情况,导致异常栈直接抛到响应里,这是不友好也不安全的。统一的异常处理是必须的。
我定义了一个
BaseController:
@Controller
public class BaseController {
protected final static Logger logger = LoggerFactory
.getLogger(&controller&);
@ResponseBody
@ExceptionHandler(Exception.class)
public RespBody exceptionHandler(Exception ex) {
return RespBody.error(&exception&, ex.getMessage());
它的作用很简单,就是定义了一个统一的异常处理逻辑。Spring MVC对异常处理的逻辑很好,如果某个
Controller类没有提供带
@ExceptionHandler 注解的方法,则会查找父类是否有这种方法,所以继承自这个
BaseController 的
Controller 都自动获得异常处理能力。
三、统一的参数校验
参数校验是必须的,而且必须放在服务器端来做,客户端的校验都是可以绕过的。
Spring MVC 当然也支持参数校验,在 Spring MVC 的配置文件里加入
&mvc:annotation-driven /& 即可以开启注解校验。
但 Spring MVC 的参数校验有些局限:
不支持对基本类型和
String 类型的参数进行校验,也就是只支持对 POJO 校验,这个非常不友好,如果一个接口只有很少的几个参数都必须定义一个 POJO 是很恼人的,要么就得手动校验,写一些 if 分支;
每个POJO后面都得有一个
BindingResult 的参数,作为对 POJO 的校验结果。
而且在每个方法里都必须对
BindingResult 进行检测,来判断参数是否合法。
在 AOP 里进行参数校验
借助 Spring 对 AOP 的支持,我们可以在 AOP 里对请求的
Controller 的方法进行拦截,做参数校验,如果校验不合格,则直接返回(因为我们已经有了统一的响应格式)。
在 AOP 里,我们可以用 Hibernate-Validator 进行手动校验,而不是通过 Spring-MVC 进行校验,这样我们就不需要在每个 POJO 后面放一个
BindingResult 参数,且 Hibernate-Validator 支持对基本类型和
String 类型的参数进行校验。
下面的代码是在 Hibernate-Validator-4.2.0-Final、validation-api-1.0.0-GA 下测试的:
首先定义一个
BindingResultHandler 类,它的方法
validate 校验请求的
Controller 的方法的参数是否合格,如果合格则继续调用业务逻辑,否则返回错误提示。
public class BindingResultHandler {
public Object validate(ProceedingJoinPoint pjp) throws Throwable {
Object target = pjp.getTarget();
MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();
Method method = joinPointObject.getMethod();
MethodValidator validator = Validation
.byProvider(HibernateValidator.class).configure()
.buildValidatorFactory().getValidator()
.unwrap(MethodValidator.class);
Set&MethodConstraintViolation&Object&& violations = validator
.validateAllParameters(target, method, pjp.getArgs(),
new Class[] {});
if (!violations.isEmpty()) {
StringBuilder sb = new StringBuilder(128);
for (ConstraintViolation&Object& violation : violations) {
sb.append(&,&).append(violation.getMessage());
return RespBody.error(sb.substring(1), &param validation failed .&);
return pjp.proceed();
AOP 配置:
&bean id=&bindingResultHandler& class=&net.coderbee.demo.controller.validation.BindingResultHandler& /&
&aop:config&
&aop:aspect id=&aspectBindingResult& ref=&bindingResultHandler&&
&aop:pointcut id=&bindingResultHandlerPointcut&
expression=&execution(public * net.coderbee.demo.controller..*Controller.*(..))& /&
&aop:around method=&validate& pointcut-ref=&bindingResultHandlerPointcut& /&
&/aop:aspect&
&/aop:config&
这样在 Controller 里就只需做注解不能完成的校验了。
@Controller
public class UserController extends BaseController {
@ResponseBody
@RequestMapping(value = &/test/valids&)
public RespBody valids(@Valid User user, @Valid Address address) {
return RespBody.ok(user);
这样的代码会简洁很多。
相关 [spring mvc web] 推荐:
- 码蜂笔记
项目组用了 Spring MVC 进行开发,觉得对里面的使用方式不是很满意,就想,如果是我来搭建开发环境,我会怎么做. 下面就是我的想法,只关注于 MVC 的 View 层. 现在基本上都是用 ajax 来调用后台接口,拿到 json格式的数据再展示,有的人直接返回数据,却没有考虑异常的情况,我觉得返回的报文里必须包含表示可能的异常信息的数据和业务响应数据.
- 企业架构 - ITeye博客
对于企业应用来说,数据是许多业务的命脉,软件通常是可替换的,但是多年积累的数据是永远不能替换的. 近些年来,以信息为中心的表述性状态转移(Representational State Transfer, REST)已成为替换传统SOAP Web服务的流行方案,为了帮助Spring开发人员,Spring3.0以上的版本中封装了对REST的良好支持.
- CSDN博客架构设计推荐文章
Web层面的框架学习了三个Struts1和2,SpringMVC,那他们之间肯定存在一个优劣和适用的环境,Struts1和2的异同点我已经做过对比《
Struts1和Struts2》,这篇将对比下Struts2和SpringMVC的异同,下面数据基本来源于网络,本人是搜集整理所得,供大家参考. 一个项目使用什么样的技术,决定的因素很多,我所能想到的有:对系统的性能、开发的效率、团队学习的成本、业务场景等,下面尽量从这几个方面入手,来分析比较下他们之间存在的优劣.
- 企业架构 - ITeye博客
大家好,Spring3 MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了. Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也很优秀. 官方的下载网址是:
http://www.springsource.org/download
(本文使用是的Spring 3.0.5版本).
- Java译站
10年前我开始自己的职业生涯的时候,Struts还是市场上的主流标准. 然而多年过后,我发现Spring MVC已经越来越流行了. 对我而言这并不意外,因为它能和Spring容器无缝集成,同时它还提供了灵活性及扩展性. 从我迄今为止对Spring的经验来看,我发现有不少人在配置Spring的时候经常会犯一些常见的错误.
- 编程语言 - ITeye博客
链接:http://gaojiewyh.iteye.com/blog/1297746 (附源码). 链接:http://zywang.iteye.com/blog/983801 . 链接:http://www.cnblogs.com/xguo/p/3163519.html . 链接:http://fuliang.iteye.com/blog/947191 .
- CSDN博客推荐文章
springmvc 框架围绕DispatcherServlet这个核心展开,DispatcherServlet是Spring MVC的总控制,它负责截获请求并将其分派给相应的处理器处理. SpringMVC框架包括注解驱动控制器、请求及响应的信息处理、视图解析、本地化解析、上传文件解析、异常处理以及表单标签绑定等内容.
- 企业架构 - ITeye博客
Spring MVC Controller单例陷阱. 标签:Spring mvc. 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明. Spring MVC Controller默认是单例的:. 1、这个不用废话了,单例不用每次都new,当然快了. 2、不需要实例会让很多人迷惑,因为spring mvc官方也没明确说不可以多例.
- 企业架构 - ITeye博客
一般情况下,对来自浏览器的请求的拦截,是利用Filter实现的,这种方式可以实现Bean预处理、后处理. Spring MVC的拦截器不仅可实现Filter的所有功能,还可以更精确的控制拦截精度. Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,继承此类,可以非常方便的实现自己的拦截器.
- 企业架构 - ITeye博客
如何在Spring MVC里面解决此问题(其它框架也一样,逻辑一样,思想一样,和具体框架没什么关系). 要解决重复提交,有很多办法,比如说在提交完成后redirect一下,也可以用本文提到的使用token的方法(我不使用redirect是因为那样解决不了ajax提交数据或者移动应用提交数据,另一个原因是现在比较通行的方法是使用token,像python里的django框架也是使用token来解决).
--> 坚持分享优质有趣的原创文章,并保留作者信息和版权声明,任何问题请联系:itarea.。使用spring mvc,可以直接把页面提交的参数转为对象,方便开发。但有时候会出现传不进参数的情况,本文通过调试spring mvc源码来分析几种传参方法.1.不带标注,原生pojo对象传参2.@RequestParam标注3.@RequestBody标注4.@PathVariable(&username&)标注这个是取@RequestMapping(value=&/login/{username}&)中的值,也就是url中的值 5.request.getParameter取参后面两种比较清晰,都是返回一个String,这个String是什么格式需要我们自己处理。前2种,我们都可以在Controller方法添加任意类型的参数。简单类型可以直接解析,String、Integer等都能正常解析.但复杂类型却不一定能解析成功。1.先看下客户端用jquery的基本例子2.服务端spring mvc Controller方法分别定义如下三种方式:public Result test(String entryWay) {public Result test(@RequestParam(&entryWay&) Integer entryWay) {public Result test(@RequestBody Integer entryWay) {前两种可以用上面的客户端参数都可正常取到值11,而第三种不行。每三种可以把Integer改String得到原始的String,再自己解析,但这样就失去了用这个标注的意义。3.分析源码,看三种方式都是怎么实现的。在以下代码处打断点:org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.getArgumentResolver(MethodParameter) line: 79 可以得到这三种情况的实现类,都实现了HandlerMethodArgumentResolver接口。
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
RequestParam
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
RequestBody
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
a.不带标注注入参数堆栈如下:可以看出,最后还调用Method.invoke方法来调用set方法来实现的注入。b.RequestParam堆栈如下:这个可以看出,这种方式用的是request.getParameterValues获得参数,传入name就是标注里的填的值.@RequestParam其实可不带参数,那么不带参数时,这个name取什么值呢?答案是取@RequestParam修饰参数的的变量名。比如:public Result test(@RequestParam String key1) 这里的name就是key1.通过asm获得,堆栈如下:ClassReader的包名为:org.springframework.asm.ClassReader c.RequestBody要与请求头的contentType参数配合使用最常用的contentType值就是application/json,在jquery中有两种方法.1.$.ajax({
beforeSend: function (xhr) {
xhr.setRequestHeader(&Content-Type&,&application/json&);
2.$.ajax({
contentType:’application/json’,
});注意上面的代码有跨域问题,与请求url同域才没有问题。后台获取这个值来找对应的HttpMessageConverter来读取传入的值,如下:最后来讨论下,如何传递自定义类参数.定义类:public class EntryWay{
public void setName(String name) {
this.name =
}后台分别用三种方式传值:public Result test(EntryWay entryWay) { public Result test(@RequestParam(&entryWay&) EntryWay entryWay) { public Result test(@RequestBody EntryWay entryWay) {第一种用这种方式传值,$.ajax({
data:&name=abc&,
})第二种没有找到可以传值的方法。第三种用下面方式传值:$.ajax({
contentType:’application/json’,
data: JSON.stringify(paramObj)
});上面写的并不是完整的代码,但都是各种方式必须的代码,并且这些代码都不一样。再记录一点,Controller的用法:一般我把把注解直接写在Controller类上面就行了,比如:@RequestMapping(&/xx&)
@RestController
public class TestController {
@RequestMapping(value = &/doRequest&)
public String doRequest(@RequestParam(&violationId&) Integer id) {
return &&;
}但我也看过这样的代码,先定义一个接口,再去实现它:@RequestMapping(&/xx&)
@RestController
public interface ViolationApi {
@RequestMapping(value = &/doRequest&)
public String doRequest(@RequestParam(&violationId&)Integer violationId);
}实现:@RestController
public class ViolationApiImpl implements ViolationApi {
public String doRequest(Integer id){
//do something
} 那么请问,这种接口加实现时。参数用&xx/doRequest?violationId=123&,还是参数用&xx/doRequest?id=123& ?答案时id才是正确的,那么这个接口中方法里的RequestParam根本没有用。有趣的是,接口中的RequestMapping等注解却用了。
Copyright (C)
北漂程序员 苏ICP备号所有源码均可去github下载【MyGitHub】https://github.com/androidwolf
Spring MVC 使用POJO对象绑定请求参数值
index.jsp前台页面加上这些,把值输入之后,通过post提交到后台。
&form action="springmvc/testPOJO" method="post"&
username: &input type="text" name="username"/&
password: &input type="password" name="password"/&
email: &input type="text" name="email"/&
age: &input type="text" name="age"/&
city: &input type="text" name="address.city"/&
province: &input type="text" name="address.province"/&
&input type="submit" value="Submit"/&
package com.hust.springmvc.
public class User {
private int
public Address getAddress() {
public void setAddress(Address address) {
this.address =
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public String getEmail() {
public void setEmail(String email) {
this.email =
public int getAge() {
public void setAge(int age) {
this.age =
public String toString() {
return "User [username=" + username + ",password=" + password + ",email=" + email + ",age=" + age + ",adress"
+ address + "]";
address.java
package com.hust.springmvc.
public class Address {
public String getProvince() {
public void setProvince(String province) {
this.province =
public String getCity() {
public void setCity(String city) {
this.city =
public String toString() {
return "Address [province=" + province + ", city=" + city + "]";
SpringMVCTest.java
package com.hust.springmvc1;
import org.springframework.stereotype.C
import org.springframework.web.bind.annotation.RequestM
import org.springframework.web.bind.annotation.SessionA
import com.hust.springmvc.entities.U
@Controller
@RequestMapping("/springmvc")
public class SpringMVCTest {
private static final String SUCCESS = "success";
* SpringMVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值。
* 支持级联属性。如 address.city、address.province 等
@RequestMapping("/testPOJO")
public String testPOJO(User user) {
System.out.println("testPOJO User: " + user);
return SUCCESS;
这个时候控制台就会收到前台传过来的所有的值,包括adress里面的city和province。
springmvc学习笔记(7)——传递对象作为参数(POJO)
SpringMVC 使用对象接收参数
SpringMVC接收复杂集合参数,集合对象
SpringMVC-----SpringMVC接收多个对象参数
SpringMVC绑定ajax传递json数据到pojo对象错误(400 Bad Request)
解决springMVC中restful的POST请求时接受json对象转换pojo对象失败问题
Spring MVC参数的传递与接收
springMVC系列(八)——springMVC参数接收详解
springMVC—接受参数以及返回参数
SpringMVC入门及系列教程(五)-响应处理&响应参数处理&SpringMVC作用域对象&SpringMVC原生Servlet对象
没有更多推荐了,

我要回帖

更多关于 springmvc工作原理 的文章

 

随机推荐