【问题标题】:SpringMVC Form validation with form:optionsSpringMVC 表单验证与表单:选项
【发布时间】:2013-01-20 10:49:04
【问题描述】:

我正在尝试在 Spring 中设置表单验证,因此我使用 javax.validation 注释。这工作得很好,它很好地解决了错误。

我的表单中有一个 form:options 字段,它从我的控制器获取预先计算的值,但如果您提交错误的数据,这些预先计算的值会丢失。

表格如下所示:

<form:form method="post" action="../add" commandName="new-booking"
        modelAttribute="new-booking" class="form-vertical">
        <table>
            <tr>
                <td><form:label path="numberOfBikesBooked">Anzahl der Fahrräder</form:label><font
                    color='red'><form:errors path='numberOfBikesBooked' /></font></td>
            </tr>
            <tr>
                <td><form:select path="numberOfBikesBooked">
                        <form:options items="${possibleBikeValues}" />
                    </form:select></td>
            </tr>
            <tr>
                <td><form:label path="firstName">Vorname</form:label><font
                    color='red'><form:errors path='firstName' /></font></td>
            </tr>
            <tr>
                <td><form:input path="firstName" /></td>
            </tr>
            <tr>
                <td><form:label path="lastName">Nachname</form:label><font
                    color='red'><form:errors path='firstName' /></font></td>
            </tr>
            <tr>
                <td><form:input path="lastName" /></td>
            </tr>
            <tr>
                <td><form:label path="mailAddress">Email</form:label><font
                    color='red'><form:errors path='mailAddress' /></font></td>
            </tr>
            <tr>
                <td><form:input path="mailAddress" /></td>
            </tr>
            <tr>
                <td><input type='submit' value='Buchen!' class="btn" /></td>
            </tr>
        </table>
        <form:hidden path="Date" />
        <form:hidden path="cancelURI" />
    </form:form>

这样的控制器(add 验证表单,AvailableBikes 呈现表单):

@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addPerson(@ModelAttribute("new-booking") @Valid Booking booking,
        BindingResult result, Map<String, Object> model) {

    if(result.hasErrors()){
        return "booking";
    }

    logger.info(String.format("Adding a Booking with the following data: Name: %s %s Email: %s Date: %s", booking.getFirstName(), booking.getLastName(), booking.getMailAddress(), booking.getDate()));

    bookingService.addBooking(booking);

    model.put("booking", booking);

    return "success";
}

@RequestMapping(value = "/AvailableBikes", method = RequestMethod.POST)
public String getAvailableBikes(@ModelAttribute("date") StringDate parDate,
        Map<String, Object> model) {

    // Parse Date
    DateFormat dateFormat = new SimpleDateFormat("dd-MM-yy");
    Date inDate = Calendar.getInstance().getTime();
    try {
        inDate = dateFormat.parse(parDate.getDate());
    } catch (ParseException e) {
        logger.severe(e.getMessage());
        e.printStackTrace();
    }

    logger.info(String.format("Listing the available Bookings for the %s", inDate));

    int availableBookings = bookingService.getAvailableBookings(inDate);
    model.put("NumAvailableBikes", Integer.toString(availableBookings));

    // TODO: Fix this with the AvailableBikesRange
    List<Integer> allPossibleBikeValues = new ArrayList<Integer>();
    for (int i = 1; i <= 30; i++) {
        allPossibleBikeValues.add(i);
    }
    model.put("possibleBikeValues", allPossibleBikeValues);

    // Get ready for new booking
    Booking booking = new Booking();
    booking.setDate(inDate);
    // TODO: How to handle the Cancel?
    booking.setCancelURI("xyz");
    model.put("new-booking", booking);

    return "booking";
}

这是模型(我认为这无关紧要):

@实体 公开课预订{

@Id
@GeneratedValue
private Integer id;

@Column(name = "date", nullable = false)
@NotNull
private Date date;

@Column(name = "numberOfBikesBooked", nullable = false)
@Min(1)
@Max(100)
private int numberOfBikesBooked;

@Column(name = "mailAddress", nullable = false)
@Email
private String mailAddress;

@Column(name = "firstName", nullable = false)
@NotBlank
@Size(min=3, max=100)
private String firstName;

@Column(name = "lastName", nullable = false)
@NotBlank
@Size(min=3, max=100)
private String lastName;

@Column(name = "cancelURI", nullable = true)
private String cancelURI;

【问题讨论】:

    标签: spring spring-mvc validation


    【解决方案1】:

    firstName 的问题在于你有两个form:input :) 第二个必须是mailAddress

    预计算值的问题很简单:当您返回视图名称字符串时,控制器不会被调用。这个案例的模型是空的。有几种解决方案:您可以将预先计算提取到方法中并在需要的地方调用它。或者(我更喜欢这种方式)您可以设置 interceptors 来填充 url 的模型:

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/context-relative-url.html" />
            <bean class="a.b.c.DropDownPopulator" />
        </mvc:interceptor>
    </mvc:interceptors>
    

    还有人口:

    public class DropDownPopulator extends HandlerInterceptorAdapter {
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            Map<String, String> result = new LinkedHashMap<String, String>(/*map for dropdown*/);
    
            modelAndView.addObject("values", result);
        }
    }
    

    【讨论】:

    • 典型的复制和粘贴错误,谢谢。对预先计算的值有任何想法吗?
    • 哇,你最好的,漂亮的编辑。我开始在谷歌上搜索拦截器,但我认为这可能是一个更简单的解决方案!只有一件事,将 XML 放在哪里?在applicationContext.xml?
    • 是的。如果尚未添加,请不要忘记添加 mvc 命名空间。当请求 URL 与配置的匹配时,将调用拦截器。
    • 我实现了 DropDownPopulator,它工作得很好。问题是,当 /add 失败时,它不会被调用,因为我在 example.com/add URL 上而不是在 example.com/AvailableBikes 上(/add 将由表单调用,并且不会改变再次,如果表格失败)。关于这个有什么想法吗?另外,是否可以检查 URL 的输入请求?
    • 是的,这是这种方法的问题。您需要在所需的每个 URL 上配置相同的拦截器。是的,您可以将拦截器添加到通配符 URL,并手动检查请求 URL,然后填充模型。
    猜你喜欢
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2020-12-11
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多