- 浏览: 958207 次
- 性别:
- 来自: 江西上饶
文章分类
- 全部博客 (460)
- p.spring (56)
- p.maven (20)
- p.ant (17)
- p.jee (18)
- p.jse (33)
- p.ofbiz (31)
- p.软件工程 (8)
- p.struts2 (5)
- p.hibernate (5)
- linux (25)
- 设计模式 (2)
- p.javascript (11)
- 硬件 (1)
- p.jsp (2)
- p.windows批处理 (1)
- 操作系统问题 (5)
- 算法 (1)
- p.mysql (7)
- p.sql (5)
- p.c (1)
- google产品 (0)
- 内存 (1)
- p.struts (1)
- p.freemarker (7)
- p.css (4)
- p.log4j (10)
- p.html (3)
- 淘宝产品 (0)
- 其他 (3)
- 编译器 (0)
- svn (4)
- p.spring.security (11)
- 图形 (0)
- p.xml (1)
- p.ssh (0)
- p.jquery (4)
- p.jdbc (3)
- p.flex (0)
- p.c++ (0)
- p.c#Net (0)
- p.assembly (0)
- p.sqlserver (0)
- p.其他 (3)
- p.webwork (21)
- p.wap (12)
- p.cglib (1)
- p.jee服务器 (11)
- windows (2)
- p.iphone (1)
- p.java.分布式与集群 (2)
- p.ibatis (16)
- p.eclipse (5)
- 架构 (2)
- http协议 (5)
- 我的个人标准 (2)
- 多线程 (1)
- 奇怪问题 (5)
- p.jira (13)
- p.httpclient (1)
- 服务器.apache (11)
- 安全防范 (1)
- p.PODAM (1)
- p.junit (16)
- fop (2)
- 硬盘安装 (1)
- powerdesigner (0)
- 单元测试 (1)
- apache commons (4)
- tomcat+apache集群 (10)
- 各类诡辩 (1)
- 安卓 (8)
- qvod (1)
- java编程基础知识考试考点及答案 (0)
- 工作总结 (4)
- oracle (0)
- spring的util工具 (3)
- json (2)
- maven (3)
- jms (19)
- p.bat (3)
- hadoop (2)
- git (3)
- nginx (1)
- p.移动开发 (1)
- shiro (3)
- 游戏破解 (1)
- react-native (7)
- ios开发 (1)
- webmagic (6)
- socks5 (1)
最新评论
-
weituotian:
说的不好,没人看的
公司系统中的菜单功能和权限功能 -
石不易:
非常详细的注解~
绑定端口和IP,Listen 与VirtualHost指令 -
spring_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
spring mvc -
liyixing1:
PandaDONG 写道谢谢你啊,我已经下下来了,只是还有很多 ...
jira war安装 -
liyixing1:
PandaDONG 写道谢谢你啊,我已经下下来了,只是还有很多 ...
jira war安装
spring 官方提供了一个例子
https://src.springframework.org/svn/spring-samples/mvc-basic/trunk
例子
我在自己的一个测试应用中会报错 错误内容大概就是:
StandardWrapper.Throwable org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.validation.beanvalidation.LocalValidatorFactoryBean#0': Invocation of init method failed; nested exception is javax.validation.ValidationException: Unable to find a default provider
这是因为我只加了validation-api-1.0.0.GA.jar架包,但是hibernate-validator-4.1.0.Final.jar架包没有加入
(hibernate-validator的版本不一定必须是是4.1.0.Final)。
另外它还需要
log4j-1.2.16.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
在调用spring.ftl的showErrors宏会调用status.errorMessages,这里的errorMessages消息是怎么生成的(因为我的项目中要考虑到国际化问题,所以需要了解,看看怎么做国际化消息提醒)。
注解适配器,在初始化参数的时候,会进入 HandlerMethodInvoker类的resolveHandlerArguments(Method, Object, NativeWebRequest, ExtendedModelMap) 方法,它会根据方法的参数的注解,来初始化数据。 其中有一句是
来确定这个参数是否需要验证。
获取这个字段的
注意这个绑定器和WebBindingInitializer绑定器不是一回事。
绑定器有效,就调用绑定方法。
doBind(binder, webRequest, validate, !assignBindingResult);
绑定方法如下
可以看出来,验证只和
这句有关系。 我们只需跟踪这里。 验证方法是
什么
https://src.springframework.org/svn/spring-samples/mvc-basic/trunk
例子
@RequestMapping(value = { "/", "home.do", "index", "index.jsp", "index.html", "index.htm" }) public String home(@Valid @ModelAttribute("user") User user, BindingResult result, ModelMap model) throws IOException { if(result.hasErrors()) { //给当前对象(BindingResult 前面的参数就是当前对象,每一个参数和BindingResult 一一对应,他们之间必须紧跟着,否则会报错,如这里的result必须跟着user,而不能将result写在model之后)注册一个字段错误。字段名可以为null,表示整个对象错误)。 result.rejectValue(null, null, null, null); System.out.println(); } List messages = new ArrayList(); messages.add("你没有登录,请先登录!"); messages.add("你输入的用户名不存在!"); messages.add("无效的账号"); model.put("messages", messages); return "application/index"; } public class User { private Integer id; private String userName; /** * * 返回 id 的值 * * @return id */ @NotNull(message = "user.id.notnull") public Integer getId() { return id; } /** * * 设置 id 的值 * * @param id */ public void setId(Integer id) { this.id = id; } }
我在自己的一个测试应用中会报错 错误内容大概就是:
StandardWrapper.Throwable org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.validation.beanvalidation.LocalValidatorFactoryBean#0': Invocation of init method failed; nested exception is javax.validation.ValidationException: Unable to find a default provider
这是因为我只加了validation-api-1.0.0.GA.jar架包,但是hibernate-validator-4.1.0.Final.jar架包没有加入
(hibernate-validator的版本不一定必须是是4.1.0.Final)。
另外它还需要
log4j-1.2.16.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
在调用spring.ftl的showErrors宏会调用status.errorMessages,这里的errorMessages消息是怎么生成的(因为我的项目中要考虑到国际化问题,所以需要了解,看看怎么做国际化消息提醒)。
注解适配器,在初始化参数的时候,会进入 HandlerMethodInvoker类的resolveHandlerArguments(Method, Object, NativeWebRequest, ExtendedModelMap) 方法,它会根据方法的参数的注解,来初始化数据。 其中有一句是
else if ("Valid".equals(paramAnn.annotationType().getSimpleName())) { validate = true; }
来确定这个参数是否需要验证。
获取这个字段的
WebDataBinder WebDataBinder binder = resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
注意这个绑定器和WebBindingInitializer绑定器不是一回事。
绑定器有效,就调用绑定方法。
doBind(binder, webRequest, validate, !assignBindingResult);
绑定方法如下
private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate, boolean failOnErrors) throws Exception { doBind(binder, webRequest); if (validate) { binder.validate(); } if (failOnErrors && binder.getBindingResult().hasErrors()) { throw new BindException(binder.getBindingResult()); } }
可以看出来,验证只和
if (validate) { binder.validate(); }
这句有关系。 我们只需跟踪这里。 验证方法是
public void validate() { //首先获取的是验证器 Validator validator = getValidator(); if (validator != null) { //然后调用验证器的验证方法,这个时候我们使用的是LocalValidatorFactoryBean验证器,但它实际上则调用它的父类SpringValidatorAdapter的验证方法,因为LocalValidatorFactoryBean没实现验证方法 validator.validate(getTarget(), getBindingResult()); } }
跟踪验证器的验证方法 public void validate(Object target, Errors errors) { //这部是调用jsr validator 的实现。不会影响spring mvc的运行结果。不做解释。这里由于我只在User模写的id属性设置的NotNull,所以只会有一个错误返回如图 result = this.targetValidator.validate(target); for (ConstraintViolation violation : result) { //这部分当然是获取验证的出错的字段名 String field = violation.getPropertyPath().toString(); //将错误字段封装成一个fieldError,因为是第一次验证这个字段,所以是null FieldError fieldError = errors.getFieldError(field); if (fieldError == null || !fieldError.isBindingFailure()) { try { //violation.getConstraintDescriptor(),返回的javax.validation.metadata.ConstraintDescriptor对象包含了这个错误字段的注解等信息。以及注解中的值,其中annotationType的信息就是注解值信息(@NotNull(message="xxx")这个时候message就是他的字段值。未设置值的字段取它的注解里面的默认值)如图 getSimpleName方法一般返回的是注解类名,如果是多个注解,组合起来返回。这个时候就返回NotNull,这个时候NotNull就作为errors.rejectValue方法的code参数 getArgumentsForConstraint方法则是通过对象名(errors保存了当前验证的对象名,如我这里验证的是action中的方法的user参数对象的id,那么就是user),字段和验证描述信息,获取国际化参数列表值,作为rejectValue方法的第三个参数(args)。第四个参数是默认消息,将注解中的message属性为默认值。很可能从属性文件取消息的时候,所使用的code就是在这里面初始化好的。所以我这里跟踪进rejectValue方法。 errors.rejectValue(field, violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(), getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor()), violation.getMessage()); } catch (NotReadablePropertyException ex) { throw new IllegalStateException("JSR-303 validated property '" + field + "' does not have a corresponding accessor for Spring data binding - " + "check your DataBinder's configuration (bean property versus direct field access)", ex); } } } } getArgumentsForConstraint方法 protected Object[] getArgumentsForConstraint(String objectName, String field, ConstraintDescriptor> descriptor) { List arguments = new LinkedList(); //将对象和字段组合user.id,字段自己id组合成一个字符串数组。 String[] codes = new String[] {objectName + Errors.NESTED_PATH_SEPARATOR + field, field}; 创建DefaultMessageSourceResolvable,以字段名(这里是id)作为默认消息,这个是在消息参数化处理的,它会在第一个参数化值{0}的处理的时候,使用codes,类似的操作去调用messageSource的getMessage(codes, "id", locale),如果没有取到,就把fieldName作为值返回,如果取到,就用这个参数值覆盖,如果没有取到,就用fileName覆盖。这个时候当然先找user.id的message,没找到找id的message,没找到就直接使用id。 arguments.add(new DefaultMessageSourceResolvable(codes, field)); // Using a TreeMap for alphabetical ordering of attribute names Map attributesToExpose = new TreeMap(); //遍历注解中的属性 for (Map.Entry entry : descriptor.getAttributes().entrySet()) { String attributeName = entry.getKey(); Object attributeValue = entry.getValue(); //判断属性是否在internalAnnotationAttributes中。internalAnnotationAttributes是以开始就初始化好的,初始化的代码如下。如果不存在,就添加进这个玩意 /*private static final Set internalAnnotationAttributes = new HashSet(3); static { internalAnnotationAttributes.add("message"); internalAnnotationAttributes.add("groups"); internalAnnotationAttributes.add("payload"); }*/ if (!internalAnnotationAttributes.contains(attributeName)) { attributesToExpose.put(attributeName, attributeValue); } } //将所有的不存在于internalAnnotationAttributes里面的属性值添加进arguments,这会使得注解中的其他属性值最为属性文件里面的变量消息值了。。这个时候由于我没有增加更多的属性,所以是空。 arguments.addAll(attributesToExpose.values()); return arguments.toArray(new Object[arguments.size()]); } errors.rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage)方法 public void rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage) { if ("".equals(getNestedPath()) && !StringUtils.hasLength(field)) { reject(errorCode, errorArgs, defaultMessage); return; } String fixedField = fixedField(field); Object newVal = getActualFieldValue(fixedField); //这里是初始化字段错误 FieldError fe = new FieldError( getObjectName(), fixedField, newVal, false, //resolveMessageCodes方法初始化codes,也就是这个字段的在属性文件中消息的key,因此大概就是在这里初始化好了这个字段所有的key,我首先的怀疑是codes包含了:{errorCode,errorCode+field}两种code(这里的errorCode的值是NotNull)。进入。 resolveMessageCodes(errorCode, field), errorArgs, defaultMessage); addError(fe); } //看来这个方法不简单,最后的codes数组不是简单的几个code,可能由多个code组合而成。继续跟踪getMessageCodesResolver方法,只是返回return this.messageCodesResolver;然后使用messageCodesResolver来生成codes,这里返回的MessageCodesResolver是org.springframework.validation.DefaultMessageCodesResolver,这个org.springframework.validation.DefaultMessageCodesResolver对象是在new BindResult对象的时候,在其AbstractBindingResult的类属性初始化好的。初始化代码是 private MessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver(); 可以看到,默认创建的MessageCodes对象是一个DefaultMessageCodesResolver,它没有设置任何属性(实际上它只有一个prefix属性) public String[] resolveMessageCodes(String errorCode, String field) { Class fieldType = getFieldType(field); return getMessageCodesResolver().resolveMessageCodes( errorCode, getObjectName(), fixedField(field), fieldType); } DefaultMessageCodesResolver的resolveMessageCodes方法 这里就是生成codes的实际方法了 public String[] resolveMessageCodes(String errorCode, String objectName, String field, Class fieldType) { List codeList = new ArrayList(); List fieldList = new ArrayList(); //这个方法的doc解释是Add both keyed and non-keyed entries for the supplied field to the supplied field list,我英文不咋的,求解释。不过暂时还用不上。 另外,静态常量CODE_SEPARATOR = "."; buildFieldList(field, fieldList); for (String fieldInList : fieldList) { //第一个code应该就是errorCode + CODE_SEPARATOR + objectName + CODE_SEPARATOR + fieldInList了,还是进去看看postProcessMessageCode方法就是一句,return getPrefix() + code;,因为我没设置前缀,所以这里的结果应该是NotNull.user.id codeList.add(postProcessMessageCode(errorCode + CODE_SEPARATOR + objectName + CODE_SEPARATOR + fieldInList)); } int dotIndex = field.lastIndexOf('.'); if (dotIndex != -1) { //将组合字段的最后一个字段名取出,如 user的name.firstName.bigChar.firstChar就是firstChar了。 buildFieldList(field.substring(dotIndex + 1), fieldList); } //这里我的结果应该是添加一个NotNull.id for (String fieldInList : fieldList) { codeList.add(postProcessMessageCode(errorCode + CODE_SEPARATOR + fieldInList)); } if (fieldType != null) { //这里我的结果就是NotNull.java.lang.Integer codeList.add(postProcessMessageCode(errorCode + CODE_SEPARATOR + fieldType.getName())); } //这里我的结果是NotNull 所以最后我的codes有四个,分别是 NotNull.user.id, NotNull.id, NotNull.java.lang.Integer, NotNull codeList.add(postProcessMessageCode(errorCode)); return StringUtils.toStringArray(codeList); } 下面就是我如果想在前面添加code的前缀,就需要设置BindingResult的MessageCodesResolver。而设置MessageCodesResolver是通过WebDataBinder的binder.setMessageCodesResolver(messageCodesResolver);设置的,他会调用getInternalBindingResult().setMessageCodesResolver(messageCodesResolver);来设置实际的BindResult来设置。如果我们要设置全局的前缀,只需写一个WebBindingInitializer,并设置到注解适配器的bean中就可以了。因为在WebBindingInitializer里面可以获取到WebDataBinder。而如果我们需要在每一个Controller类添加不同的前缀,只需要写一个@InitBinder注解过的方法就好了。 @InitBinder() public void initBinder(WebDataBinder binder) { DefaultMessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver(); messageCodesResolver.setPrefix("user."); binder.setMessageCodesResolver(messageCodesResolver); } 在ftl中展示字段错误,是通过showErrors 来暂时字段错误的。 "/> 我们一般在showErrors 之前需要调用一次formInput ,才能让showErrors正常工作 因为formInput 会调用bind宏,来初始化这个字段对应的status ${error} #if> ${error} #if> ${separator}#if> #list> #macro> 而bind宏则是 #if> #if> #macro> 可以看出来,bind宏每次调用之后,都会重新定义status和stringStatusValue 所以才能让showErrors 正常工作。 首先status对应的类型是org.springframework.web.servlet.support.BindStatus类型。 进到它的 public String[] getErrorMessages() { initErrorMessages(); return this.errorMessages; } 方法,可以发现首先需要initErrorMessages初始化消息。 if (this.errorMessages == null) { this.errorMessages = new String[this.objectErrors.size()]; for (int i = 0; i (); } Errors errors = this.errorsMap.get(name); boolean put = false; if (errors == null) { //从这里可以看出,BindResult对象在model中,以org.springframework.validation.BindingResult.(MODEL_KEY_PREFIX 的值是org.springframework.validation.BindingResult.)+对象名方式命名,这里是org.springframework.validation.BindingResult.user errors = (Errors) getModelObject(BindingResult.MODEL_KEY_PREFIX + name); // Check old BindException prefix for backwards compatibility. if (errors instanceof BindException) { errors = ((BindException) errors).getBindingResult(); } if (errors == null) { return null; } put = true; } if (htmlEscape && !(errors instanceof EscapedErrors)) { errors = new EscapedErrors(errors); put = true; } else if (!htmlEscape && errors instanceof EscapedErrors) { errors = ((EscapedErrors) errors).getSource(); put = true; } if (put) { this.errorsMap.put(name, errors); } return errors; } codes大概内容是 NotNull.user.id(errorCode.+objectName.field)优先级 0 NotNull.id(errorCode.+fieldLastName)优先级 1 NotNull.java.lang.Integer(errorCode.+fieldType.getName())优先级 2 NotNull(errorCode)优先级 3 参数无法转换 以Date类型作为例子 当出现请求参数无法转换成Date类型。直接输出字段error,就会发现,输出的是异常的message。 调试发现它这个时候的codes是 [typeMismatch.activitySave.activityStartTime, typeMismatch.activityStartTime, typeMismatch.java.util.Date, typeMismatch]
评论
4 楼
gnomewarlock
2013-12-02
代码自己能看懂吗?
3 楼
clamy01
2013-08-30
这代码看着真揪心!!!
2 楼
liyixing1
2012-11-09
wkq72376 写道
messages
什么
1 楼
wkq72376
2012-10-16
messages
发表评论
-
Spring 定时任务,cron表达式,@Scheduled cron表达式
2016-04-25 15:48 5296一个cron表达式有至少6 ... -
spring mvc list
2015-12-14 10:28 1284我使用这样无法传入 @requestMapping(" ... -
Unable to locate Spring NamespaceHandler for XML schema namespace
2015-09-23 14:00 2322org.springframework.beans.facto ... -
关于使用s.url jstl的上下文
2015-08-16 13:28 917比如 [@s.url '/'/]index.html?cote ... -
Spring 属性占位符配置器 PropertyPlaceholderConfigurer
2015-08-02 12:43 2082<!-- 属性配置文件读 ... -
FactoryBean接口
2014-09-30 14:05 908实现了FactoryBean接口的bean不是简单的一个bea ... -
国际化之MessageSourceAware和MessageSourceAccessor
2014-01-06 23:13 2853先看接口MessageSourceAware 该接口的注释中 ... -
spring 惯例优先原则
2013-07-22 09:46 1211惯例优先原则(convention over configur ... -
ant path匹配
2013-07-22 09:40 2174spring和ant path实现相关的主要类有两个 org. ... -
springmvc action方法中参数具有@ModelAttribute与不具有的区别
2012-12-14 09:36 4114在springmvc的参数解析中,发现具有@ModelAttr ... -
util包
2012-12-05 13:50 1107spring的util基本上都在springframework ... -
url,请求相关帮助类UrlPathHelper
2012-11-29 11:18 2519org.springframework.web.util.Ur ... -
整站国际化方案
2012-11-28 17:46 1108当前常见的实现方式,主要由两种方案实现 1.通过locale ... -
spring的三种注入方式
2012-11-20 17:30 18671.通过bean的property子元 ... -
spring AnnotationUtils 注解工具
2011-12-08 11:27 1303spring AnnotationUtils 注解工具 -
GenericCollectionTypeResolver,用于获取list或者map等元素的类型
2011-12-07 16:17 1311GenericCollectionTypeResolver,用 ... -
属性编辑器
2011-12-05 18:19 1079我自定义了一个类型,然后设置了一个属性编辑器,注册的class ... -
iframe下面的session问题
2011-12-04 19:52 5320在写iframe完成长连接获取上传状态的时候,有两次请求,一次 ... -
mvc之类的驱动原理
2011-12-01 09:34 1097<mvc:annotation-driven /> ... -
Couldn't access current invocation
2011-10-20 20:44 1895做了一个aop的日志记录器,但是在运行的时候出现了日志信息 服 ...
相关推荐
7. **数据绑定和验证**:`@Valid`注解结合JSR 303/349提供的bean验证,可以在处理请求时自动进行数据验证。 8. **拦截器**:`@AspectJ`风格的切面注解,如`@Before`和`@After`,可以创建拦截器,实现请求前后的处理...
总结来说,Spring MVC的注解式控制器提供了强大的数据验证、类型转换和格式化功能,简化了Web开发过程,提升了应用的安全性和用户体验。通过合理利用这些特性,开发者可以构建更加健壮、易于维护的Web应用。
`@RequestBody`用于将HTTP请求体中的数据转换为方法参数,而`@ResponseBody`将方法返回值直接写入HTTP响应体,通常用于返回JSON或XML格式的数据。 8. **@ModelAttribute** `@ModelAttribute`常用于数据绑定,它...
8. **Validation 验证**:通过 `@Valid` 和 `javax.validation` 注解,可以在处理请求时对输入数据进行验证。 9. **配置类**:Spring 4.0 引入了 Java 配置,允许开发者用类代替 XML 配置。`@Configuration` 和 `@...
- **标准支持**:SpringMVC支持JSR-303标准的注解验证,如`@NotNull`、`@Pattern`等,简化了验证逻辑的编写。 - **集成便利**:只需在控制器方法的参数前加上`@Valid`或`@Validated`注解,并配合`BindingResult`对象...
它们与`@ModelAttribute`一起使用,但更专注于表单验证和数据绑定: ```java @PostMapping("/submit") public String submitForm(@Validated @ModelAttribute("form") FormCommand command, BindingResult ...
7. **转换与格式化**:SpringMVC支持自定义转换器和格式化器,用于处理不同类型的请求参数和响应数据,如日期、货币等的格式化。 8. **RESTful支持**:SpringMVC通过@RequestMapping的pathVariable、MatrixVariable...
Spring MVC提供了数据绑定和验证机制,可以通过`@Valid`注解配合`@NotBlank`, `@Size`等JSR-303/JSR-349验证注解来验证接收到的数据。如果数据不合法,Spring MVC会自动返回错误信息。 7. **配置支持** 要使Spring...
同时,@RequestParam、@PathVariable、@ModelAttribute等注解用于从请求中提取参数。 **总结** "IDEA社区版编写的SpringMVC小项目"涵盖了SpringMVC的基本使用,包括了文件上传和JSON解析两个常见功能。这个项目...
扩展Spring MVC以支持绑定JSON格式的请求参数,能够使我们的服务更好地与前端或API客户端进行交互。本文将深入探讨如何实现这一功能。 首先,我们需要了解Spring MVC的模型绑定机制。模型绑定是Spring MVC中的一项...
在Spring MVC框架中,配置方式主要有两种:一种是基于XML的配置,另一种是基于Java的注解配置。本文将详细探讨非注解...这种方式虽然比注解配置繁琐,但在某些场景下,如需要灵活控制组件行为时,仍有一定的应用价值。
在SpringMVC中,请求参数可以通过注解如@RequestParam、@PathVariable和@RequestBody进行获取。例如,使用@RequestParam可以将请求参数绑定到方法参数上。对于复杂的表单数据,可以使用@ModelAttribute注解结合...
改造可能需要定制化这些行为,比如自定义转换器或验证器,以适应特定的数据格式或业务规则。 7. **异常处理**: 应用程序可能需要统一处理各种异常情况。SpringMVC允许自定义异常处理器,改造时可能需要增加或修改...
注解驱动的SpringMVC简化了配置,常见的注解有: 1. `@Controller`:标记控制器类。 2. `@RequestMapping`:用于映射URL,可以指定标准映射、Ant风格映射和占位符映射,并限定请求方法。 3. `@PathVariable`:获取...
- 最佳实践是定义全局日期格式,或使用`WebMvcConfigurer`接口自定义日期格式转换。 15. 请求URL匹配: - `'?'`形式的URL:用于匹配单个动态段,如`/user/{id}?`。 - `'*'`形式的URL:用于匹配多个动态段,如`/...
- `@ResponseBody`注解用于将方法返回的对象转换为JSON或XML格式,直接写入HTTP响应体。 - 可以使用`ResponseEntity`对象更精细地控制响应状态码和头部信息。 6. **异常处理** - 使用`@ExceptionHandler`注解...
在Spring MVC框架中,数据类型转换、数据格式化和数据校验是开发Web应用程序时不可或缺的部分。这些功能有助于确保从客户端接收到的数据准确无误,同时提供了一种优雅的方式来处理和展示这些数据。本篇文章将深入...
6. **转换器和格式化器**:SpringMVC提供了`@InitBinder`和`@DateTimeFormat`等注解,用于自定义数据绑定和格式化逻辑。 7. **异常处理**:`@ExceptionHandler`注解允许我们为特定类型的异常定义处理方法,这样可以...
在Spring MVC中,`@RequestBody`注解是用于将HTTP请求体中的数据转换为Java对象的,特别适用于处理JSON或XML格式的数据。当控制器方法接收POST、PUT等带有请求体的HTTP请求时,`@RequestBody`可以帮助我们将接收到的...
在默认情况下,Spring MVC使用`WebDataBinder`来处理数据绑定,它可以将请求参数与Java对象的字段进行匹配,并通过类型转换器(`Converter`)和格式化器(`Formatter`)将字符串值转化为对象类型。如果遇到无法直接...