Spring MVC 的 URL 映射决定请求由哪个方法处理,参数注解决定值从哪里取得。字段同名不表示来源相同,也不应在同一方法叠加 @PostMapping 与 @RequestMapping 来表达两个入口。
两个只读路径共用一个方法
下面按 Spring Framework 5 的 API 写一个完整控制器,直接返回 JSON 数据而不依赖额外视图模板:
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ItemExampleController {
@GetMapping({"/items/{itemId}/detail",
"/items/{itemId}/{stationId}/detail"})
public Map<String, String> detail(
@PathVariable("itemId") String itemId,
@PathVariable(name = "stationId", required = false)
String stationId) {
Map<String, String> result = new LinkedHashMap<>();
result.put("itemId", itemId);
result.put("stationId", stationId == null ? "default" : stationId);
return result;
}
@PostMapping("/items/{itemId}/edit")
public Map<String, String> edit(
@PathVariable("itemId") String itemId,
@RequestParam("name") String name) {
Map<String, String> result = new LinkedHashMap<>();
result.put("itemId", itemId);
result.put("name", name);
return result;
}
}
第二个方法只展示表单参数接收,不执行实际保存。正式修改接口还需校验和权限判断,不能把演示回显当作完成更新。
缺省路径变量应有确定含义
/items/123/detail 没有 stationId,/items/123/warehouse/detail 则有。required=false 允许前一种映射,方法必须明确缺省分支;这里用 default 表示演示值,不替业务决定默认站点。
一个映射注解的 value/path 可以列出多个模式,不需要在同一方法叠加互相竞争的请求映射。Spring 5 RequestMapping API
路径、请求参数与模型对象分开看
@PathVariable 明确取路径值;@RequestParam 常用于查询串或表单字段。复杂表单可以模型绑定,但不能只凭对象里存在同名 itemId 字段,就假定一定取得了希望的来源。
若路径里有 ID,表单又提交一个 ID,应明确以谁为准并处理冲突,最好不要让客户端修改不应绑定的标识。白名单可参见 WebDataBinder 允许字段。
共用方法不等于共用授权结论
两个入口仍需各自核对访问权限。GET 用于读取,不应因参数方便就承担保存动作;基于会话的修改表单还需 CSRF 防护。映射成功、绑定成功和业务允许修改,是三个分别检查的环节。