Spring MVC 4中JSP多按钮AJAX调用结合JSR303验证实现问询
嘿,作为Spring MVC 4和jQuery的新手,碰到这种多组独立AJAX提交还要保留JSR 303验证的场景确实容易懵圈,我来给你分享两个实用的解决方案,完美解决你的问题:
方案一:Spring Form标签+按钮区分+AJAX拦截提交
这个方案保留你提到的Spring Form标签数据绑定能力,通过给按钮设置唯一标识来区分操作,用jQuery拦截默认表单提交,只处理对应组的验证和逻辑:
1. JSP页面代码
<form:form modelAttribute="campusModel" method="post" id="campusForm" action="/campus/process"> <!-- 第一组组件 --> <div class="input-group"> <label>DataSet1:</label> <form:input path="dataset1" cssClass="form-control" /> <form:errors path="dataset1" cssClass="text-danger" /> <button type="submit" name="action" value="process1" class="btn btn-primary">Process1</button> <label>Result1:</label> <form:input path="resultSet1" cssClass="form-control" readonly="true" /> </div> <!-- 第二组组件 --> <div class="input-group"> <label>DataSet2:</label> <form:input path="dataset2" cssClass="form-control" /> <form:errors path="dataset2" cssClass="text-danger" /> <button type="submit" name="action" value="process2" class="btn btn-primary">Process2</button> <label>Result2:</label> <form:input path="resultSet2" cssClass="form-control" readonly="true" /> </div> </form:form>
2. jQuery AJAX拦截逻辑
$(document).ready(function() { $('#campusForm').submit(function(e) { // 阻止默认的全表单提交行为 e.preventDefault(); var $form = $(this); // 获取当前点击的按钮标识(通过name="action"的value区分) var currentAction = $('button[name="action"]:focus').val(); var formData = $form.serialize(); $.ajax({ url: $form.attr('action'), type: $form.attr('method'), data: formData, dataType: 'json', success: function(response) { // 清空所有错误提示 $('.text-danger').html(''); // 根据操作更新对应结果域 if (currentAction === 'process1') { $('input[name="resultSet1"]').val(response.resultSet1); } else if (currentAction === 'process2') { $('input[name="resultSet2"]').val(response.resultSet2); } // 处理后端返回的验证错误 if (response.errors) { $.each(response.errors, function(field, msg) { $('form:errors[path="' + field + '"]').html(msg); }); } }, error: function(xhr) { $('.text-danger').html(''); var errors = xhr.responseJSON; $.each(errors, function(field, msg) { $('form:errors[path="' + field + '"]').html(msg); }); } }); }); });
3. Spring MVC控制器代码
@Controller @RequestMapping("/campus") public class CampusController { // 初始化模型对象 @ModelAttribute("campusModel") public CampusModel initModel() { return new CampusModel(); } @PostMapping("/process") @ResponseBody public ResponseEntity<?> handleProcess(@Validated @ModelAttribute("campusModel") CampusModel model, @RequestParam("action") String action, BindingResult bindingResult) { // 只验证当前操作对应的字段,避免全表单验证 if ("process1".equals(action)) { validateSingleField(model, "dataset1", bindingResult); } else if ("process2".equals(action)) { validateSingleField(model, "dataset2", bindingResult); } // 验证失败返回错误信息 if (bindingResult.hasErrors()) { Map<String, String> errorMap = new HashMap<>(); for (FieldError error : bindingResult.getFieldErrors()) { errorMap.put(error.getField(), error.getDefaultMessage()); } return ResponseEntity.badRequest().body(errorMap); } // 执行对应业务逻辑 if ("process1".equals(action)) { model.setResultSet1("处理结果:" + model.getDataset1()); } else if ("process2".equals(action)) { model.setResultSet2("处理结果:" + model.getDataset2()); } return ResponseEntity.ok(model); } // 工具方法:单独验证某个字段 private void validateSingleField(CampusModel model, String fieldName, BindingResult result) { Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<CampusModel>> violations = validator.validateProperty(model, fieldName); for (ConstraintViolation<CampusModel> violation : violations) { result.addError(new FieldError("campusModel", fieldName, violation.getMessage())); } } }
4. 模型类(带JSR303注解)
public class CampusModel { @NotEmpty(message = "DataSet1不能为空") private String dataset1; private String resultSet1; @NotEmpty(message = "DataSet2不能为空") private String dataset2; private String resultSet2; // 省略getter和setter }
方案二:普通Button+手动触发验证+AJAX提交
如果不想用submit按钮,也可以用普通button,通过自定义属性区分操作,手动控制验证和提交逻辑:
1. JSP按钮修改
把submit按钮改成普通按钮,添加data-action属性:
<button type="button" data-action="process1" class="btn btn-primary">Process1</button> <button type="button" data-action="process2" class="btn btn-primary">Process2</button>
2. jQuery逻辑调整
$(document).ready(function() { $('.btn-primary').click(function() { var action = $(this).data('action'); var $form = $('#campusForm'); var formData = $form.serialize() + '&action=' + action; $.ajax({ url: $form.attr('action'), type: $form.attr('method'), data: formData, dataType: 'json', success: function(response) { // 逻辑和方案一一致,更新结果和错误提示 $('.text-danger').html(''); if (action === 'process1') { $('input[name="resultSet1"]').val(response.resultSet1); } else if (action === 'process2') { $('input[name="resultSet2"]').val(response.resultSet2); } if (response.errors) { $.each(response.errors, function(field, msg) { $('form:errors[path="' + field + '"]').html(msg); }); } }, error: function(xhr) { $('.text-danger').html(''); var errors = xhr.responseJSON; $.each(errors, function(field, msg) { $('form:errors[path="' + field + '"]').html(msg); }); } }); }); });
控制器代码和方案一完全一致,不需要修改。
关键注意事项
- 确保Spring MVC配置了JSR303验证支持:XML配置添加
<mvc:annotation-driven />,Java配置添加@EnableWebMvc。 - 项目中要引入Jackson依赖,保证控制器能正常返回JSON格式数据。
- 两个方案都实现了组间互不干扰:点击Process1只会验证DataSet1并更新Result1,Process2同理。
内容的提问来源于stack exchange,提问作者Phoenix
相关产品推荐
相关产品推荐

