You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
                });
            }
        });
    });
});

控制器代码和方案一完全一致,不需要修改。


关键注意事项

  1. 确保Spring MVC配置了JSR303验证支持:XML配置添加<mvc:annotation-driven />,Java配置添加@EnableWebMvc。
  2. 项目中要引入Jackson依赖,保证控制器能正常返回JSON格式数据。
  3. 两个方案都实现了组间互不干扰:点击Process1只会验证DataSet1并更新Result1,Process2同理。

内容的提问来源于stack exchange,提问作者Phoenix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:15:36