如何在HTML与Spring Boot中复用表单的两个文本输入字段?
问题描述
我是HTML和Spring Boot新手,正在开发一个具备加、减、乘功能的简易计算器。原本设置了3个表单块分别对应Spring Boot的3个接口,希望复用乘法表单块中的num1和num2输入字段到加法、减法表单中,但目前只有乘法功能正常,加法和减法提交时会把num1和num2的值传为null,抛出错误:
java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "num1" is null
原Index.html代码:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Calculator</title> </head> <body> <h1>Simple Calculator</h1> <!-- Add form --> <form action="/add" method="post"> <br> <button type="submit">Add</button> </form> <!-- Subtract form --> <form action="/subtract" method="post"> <br> <button type="submit">Subtract</button> </form> <!-- Multiply form --> <form action="/multiply" method="post"> <label for="num1">Number 1:</label> <input type="text" id="num1" name="num1" th:value="${num1 != null ? num1 : ''}"> <label for="num2">Number 2:</label> <input type="text" id="num2" name="num2" th:value="${num2 != null ? num2 : ''}"> <br> <button type="submit">Multiply</button> <br> <br> <label for="result">Result:</label> <input type="text" id="result" th:value="${result}" readonly> </form> </body> </html>
原Controller代码:
package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class HelloWorldController { @PostMapping("/add") public String add(@RequestParam(value = "num1", required = false) Integer num1, @RequestParam(value = "num2", required = false) Integer num2, Model model) { int result = num1 + num2; model.addAttribute("result", result); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; // Return to the same page with updated data } @PostMapping("/subtract") public String subtract(@RequestParam(value = "num1", required = false) Integer num1, @RequestParam(value = "num2", required = false) Integer num2, Model model) { int result = num1 - num2; model.addAttribute("result", result); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } @PostMapping("/multiply") public String multiply(@RequestParam(value = "num1", required = false) Integer num1, @RequestParam(value = "num2", required = false) Integer num2, Model model) { int result = num1 * num2; model.addAttribute("result", result); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } }
问题原因
加法和减法表单里没有包含num1和num2输入字段,表单提交时只会发送当前表单内的元素数据,所以这两个参数会被传为null,触发空指针异常。
解决方案
方案一:合并为单个表单(推荐)
只保留一个表单,利用HTML5的formaction属性为不同按钮指定提交地址,实现输入框复用,代码最简洁。
修改后的Index.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Calculator</title> </head> <body> <h1>Simple Calculator</h1> <!-- 单个表单共享输入框 --> <form method="post"> <label for="num1">Number 1:</label> <input type="text" id="num1" name="num1" th:value="${num1 != null ? num1 : ''}"> <label for="num2">Number 2:</label> <input type="text" id="num2" name="num2" th:value="${num2 != null ? num2 : ''}"> <br><br> <!-- 每个按钮指定对应接口地址 --> <button type="submit" formaction="/add">Add</button> <button type="submit" formaction="/subtract">Subtract</button> <button type="submit" formaction="/multiply">Multiply</button> <br> <br> <label for="result">Result:</label> <input type="text" id="result" th:value="${result}" readonly> </form> </body> </html>
修改后的Controller(增加空值判断)
package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class HelloWorldController { @PostMapping("/add") public String add(@RequestParam(value = "num1", required = false) Integer num1, @RequestParam(value = "num2", required = false) Integer num2, Model model) { // 空值校验,避免空指针并提示用户 if (num1 == null || num2 == null) { model.addAttribute("result", "请输入有效数字"); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } int result = num1 + num2; model.addAttribute("result", result); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } @PostMapping("/subtract") public String subtract(@RequestParam(value = "num1", required = false) Integer num1, @RequestParam(value = "num2", required = false) Integer num2, Model model) { if (num1 == null || num2 == null) { model.addAttribute("result", "请输入有效数字"); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } int result = num1 - num2; model.addAttribute("result", result); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } @PostMapping("/multiply") public String multiply(@RequestParam(value = "num1", required = false) Integer num1, @RequestParam(value = "num2", required = false) Integer num2, Model model) { if (num1 == null || num2 == null) { model.addAttribute("result", "请输入有效数字"); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } int result = num1 * num2; model.addAttribute("result", result); model.addAttribute("num1", num1); model.addAttribute("num2", num2); return "index"; } }
方案二:用Thymeleaf片段复用输入框(保留三个表单)
如果需要保留三个独立表单,可以把输入框做成Thymeleaf片段,在每个表单中引用实现复用。
1. 创建片段文件src/main/resources/templates/fragments/inputs.html
<div th:fragment="number-inputs"> <label for="num1">Number 1:</label> <input type="text" id="num1" name="num1" th:value="${num1 != null ? num1 : ''}"> <label for="num2">Number 2:</label> <input type="text" id="num2" name="num2" th:value="${num2 != null ? num2 : ''}"> <br> </div>
2. 修改Index.html引用片段
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Calculator</title> </head> <body> <h1>Simple Calculator</h1> <!-- Add form --> <form action="/add" method="post"> <div th:replace="~{fragments/inputs :: number-inputs}"></div> <button type="submit">Add</button> </form> <!-- Subtract form --> <form action="/subtract" method="post"> <div th:replace="~{fragments/inputs :: number-inputs}"></div> <button type="submit">Subtract</button> </form> <!-- Multiply form --> <form action="/multiply" method="post"> <div th:replace="~{fragments/inputs :: number-inputs}"></div> <button type="submit">Multiply</button> <br> <br> <label for="result">Result:</label> <input type="text" id="result" th:value="${result}" readonly> </form> </body> </html>
3. Controller代码同方案一(需保留空值判断)
说明
- 方案一的
formaction是HTML5原生特性,无需额外依赖,能大幅简化代码结构。 - 空值判断是必要的,既可以避免空指针异常,也能给用户提供明确的操作提示。
内容的提问来源于stack exchange,提问作者Gautam S
相关产品推荐
相关产品推荐

