ajax提交复杂对象
1. 提交的对象类UserDetail:
public class User {
@NotBlank
private String id;
@NotBlank
private String userName;
}
public class UserDetail {
@NotNull
private User user;
private String details;
}
2. controller的代码:
@RequestMapping(value = "api/user/add", method = { RequestMethod.PUT, RequestMethod.POST })
@ResponseBody
public String add(@RequestBodyUserDetail userDetail) {
System.out.print(userDetail);
return "success";
}
3. ajax提交的代码,红色部分是关键代码,①处不写对会报400错;②处不这样写,后端无法接收
var user = {
userName : $("#userName").val()
}
var userDetail = {
user : user,
detail : $("#detail").val()
};
$.ajax({
type : 'POST',
dataType : "JSON",
contentType:"application/json", //①
cache : false,
url : url,
data : JSON.stringify(datas),
async : false,
success : function(result) {
alert("成功");
},
error : function(result) {
alert("失败");
}
});
后端校验
在做校验的时候踩了几个坑,这里主要是把坑记录下来
坑1:
springboot的校验,首先考虑用@Valid做,于是在Controller代码里加入注解
public String add(@Valid@RequestBodyUserDetail userDetail) {
System.out.print(userDetail);
return "success";
}
很快发现问题,此处Valid的校验只会对按照UserDetail类里的校验规则做校验,而不会对其引用对象user校验,如User类里要求userName不为空,但此时校验不会校验userName。即没有对嵌套的内层对象做校验。
解决:在UserDetail类的user对象上加上@Valid注解
public class UserDetail {
@NotNull
@Valid
private User user;
private String details;
}
写个测试方法,测试正常:
publicclass ValidationTest {
privatestaticfinal Validator validator;
// 获得验证器实例
static {
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
validator = factory.getValidator();
factory.close();
}
publicstaticvoid main(String[] args) throws ParseException {
User user = new User();
UserDetail userDetail = new UserDetail ();
user.setSysUser(user);
Set<ConstraintViolation<UserDetail>> violations = validator.validate(userDetail);
if (violations.size() == 0) {
System.out.println("No violations.");
} else {
System.out.printf("%s violations:%n", violations.size());
violations.stream().forEach(ValidationTest::printError);
}
}
privatestaticvoid printError(ConstraintViolation<?> violation) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}
}
坑2:
加上@Valid之后,前台直接报400错误,后台没有任何异常打印信息,userDetails也没有打印出来。推测此时验证已经生效,但绑定过程异常,并且该异常没有被BindException捕获(简单对象的验证错误是可以用这个异常捕获的)。
几经周折,最后发现这里报的异常是MethodArgumentNotValidException,于是添加对这个异常的全局处理,问题解决
改进:考虑了一下,在Controller层使用@Valid来做校验体验不好,直接手动校验逻辑会更加清楚
写一个校验工具类BeanValidators
publicclass BeanValidators {
/**
* 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
publicstaticvoid validateWithException(Validator validator, Object object, Class<?>... groups)
throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
thrownew ConstraintViolationException(constraintViolations);
}
}
/**
* 辅助方法,
* 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>.
*/
publicstatic List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<message>
*/
@SuppressWarnings("rawtypes")
publicstatic List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = Lists.newArrayList();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
returnerrorMessages;
}
/**
* 辅助方法,
* 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property,
* message>.
*/
publicstatic Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>.
*/
@SuppressWarnings("rawtypes")
publicstatic Map<String, String> extractPropertyAndMessage(
Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = Maps.newHashMap();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
}
returnerrorMessages;
}
/**
* 辅助方法,
* 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath
* message>.
*/
publicstatic List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}
/**
* 辅助方法, 转换Set<ConstraintViolations>为List<propertyPath message>.
*/
@SuppressWarnings("rawtypes")
publicstatic List<String> extractPropertyAndMessageAsList(
Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}
/**
* 辅助方法,
* 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath
* +separator+ message>.
*/
publicstatic List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<propertyPath +separator+ message>.
*/
@SuppressWarnings("rawtypes")
publicstatic List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations,
String separator) {
List<String> errorMessages = Lists.newArrayList();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
returnerrorMessages;
}
}
Controller层调用代码(object是需要验证的类):
protected Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
try {
BeanValidators.validateWithException(validator, user);
} catch (ConstraintViolationException e) {
List<String> list = BeanValidators.extractPropertyAndMessageAsList(e, ": ");
list.add(0, "数据验证失败:");
//处理逻辑
}
相关推荐
项目描述 在上家公司自己集成的一套系统,用了两个多月的时间完成的:Springboot+Mybatis-plus+ SpringMvc+Shiro+Redis企业级开发系统 Springboot作为容器,使用mybatis作为持久层框架 使用官方推荐的thymeleaf做为...
结合Jquery Ajax,整合前端Layer.js(提供弹窗)+Bootstrap-table(数据列表展示)+ Bootstrap-Export(各种报表导出SQL,Excel,pdf等)框架,整合Echars,各类图表的展示(折线图,饼图,直方图等),使用了layui的...
一、项目简述 功能: 用户管理模块:用户登录、用户注册、修改密码 榜单列表模块:动态地从数据库中获取...项目技术: JSP +SpringBoot + MyBatis + html+ css + JavaScript + JQuery + Ajax + Bootstrap+ maven 等等。
一、项目简述 本系统功能包括: 学生管理,教师管理,课程管理,成绩管理,系统管理等等。 二、项目运行 环境配置: ...Springboot + Maven + mybatis+ Vue 等等组成,B/S模式 + Maven管理等等。
一、项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持) ...Springboot+ SpringMVC + JPA+ Jsp + Html+ JavaScript + JQuery + Ajax + maven等等
Java社区系统源码并提供详细的开发文档和配套教程,包含帖子、评论、私信、系统通知、点赞、关注、搜索、用户设置、数据统计等模块。 核心技术栈 后端: Spring Spring Boot 2.1.5 RELEASE ...Ajax
1. 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,Eclipse/MyEclipse导入时,若为maven项目请选择maven; 若为maven项目,导入成功后请...
springboot + mybatis + bootstrap + jqgrid + ajax + elasticsearch(用到在整合) + redis(用到在整合) 项目编码: UTF-8 项目名称: poem 数据库名称: poem 项目中包结构: src/main/java com.baizh.xxx ...
一、项目简述 系统功能: ... 二、项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe ...项目技术: JSP +Springboot+ SpringMVC + MyBatis + ThymeLeaf + HTML+ JavaScript + JQuery + Ajax + maven等等
SpringBoot与Ajax是现代Web开发中的两个重要技术,它们结合使用可以实现前后端的高效协作。SpringBoot简化了Spring框架的配置,提供了快速构建独立应用的能力,而Ajax则实现了页面的无刷新更新,提升了用户体验。 ...
在IT领域,构建高效、简洁的应用程序框架是开发工作中的重要环节。本项目"springboot+mybatis+bootstrap整合的简单框架"旨在提供一个快速开发的解决方案,将三个流行的开源技术——Spring Boot、MyBatis和Bootstrap...
SpringBoot+MyBatis+Json+javaScrip+Ajax+Html5的毕业设计项目, 餐厅收银和订座系统, 前后端都有,提供项目源码与注释,数据库sql文件,进行二次开发,简单配置即可上手使用
一、项目简述 功能包括: 用户分为患者,医生,管理员,患者可进行注册选择医生挂号,选择日期,选择号源,医生...JSP +Spring + SpringBoot + MyBatis + html+ css + JavaScript + JQuery + Ajax + layui+ maven等等
通过Spring Initializr快速生成springboot项目+mybatis generator反向生成代码+easyui 的表单设计(增删改查-分页)+ajax异步操作+mysql源数据库+单元测试+详细注解及个人编程的运到困难
一、项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持) ...HTML +Springboot+ SpringMVC + MyBatis + ThymeLeaf + JavaScript + JQuery + Ajax + maven等等.