基础参数绑定方式

在控制器方法中直接声明方法参数是最简单的参数获取方式。Spring MVC会自动尝试将请求参数与同名方法参数进行绑定:

@GetMapping("/search")

public String productSearch(

@RequestParam String keyword,

@RequestParam(defaultValue = "1") int page,

@RequestParam(required = false) String sort) {

// 使用参数进行业务处理

return "searchResults";

}

实际开发中建议显式使用@RequestParam注解,通过required属性控制参数必填性,defaultValue设置默认值。当请求参数名与方法参数名不一致时,可以使用name属性指定映射关系:

@RequestParam(name = "q") String searchTerm

RESTful风格参数处理

对于RESTful接口设计,路径参数的处理需要使用@PathVariable:

@GetMapping("/products/{id}/details")

public Product getProductDetails(

@PathVariable Long id,

@PathVariable String category) {

return productService.getDetails(id, category);

}

复杂路径参数处理可以通过正则表达式约束:

@GetMapping("/orders/{year:\\d{4}}-{month:\\d{2}}")

public List getMonthlyOrders(

@PathVariable int year,

@PathVariable String month) {

return orderService.findByMonth(year, month);

}

结构化参数绑定

当处理包含多个字段的表单时,使用对象绑定可以简化代码:

@PostMapping("/register")

public String handleRegistration(UserForm form) {

// 自动将请求参数绑定到UserForm对象

userService.register(form);

return "redirect:/welcome";

}

// 表单对象

public class UserForm {

@NotBlank

private String username;

@Email

private String email;

@Size(min=8, max=20)

private String password;

// getters/setters

}

配合验证注解进行参数校验,需要在方法参数前添加@Valid注解:

public String handleRegistration(@Valid UserForm form, BindingResult result) {

if (result.hasErrors()) {

return "registrationForm";

}

// ...

}

JSON请求体处理

现代API开发中处理JSON请求体已成为标配:

@PostMapping("/api/products")

public ResponseEntity createProduct(

@RequestBody ProductCreateRequest request) {

Product created = productService.create(request);

return ResponseEntity.created(URI.create("/products/"+created.getId()))

.body(created);

}

处理复杂嵌套结构时,建议定义明确的DTO:

public class OrderCreateDTO {

@NotNull

private Long userId;

@Valid

@NotEmpty

private List items;

// 嵌套对象验证

public static class OrderItemDTO {

@NotBlank

private String sku;

@Min(1)

private int quantity;

}

}

自定义参数解析

实现自定义参数解析器可以处理特殊场景:

public class ClientInfoArgumentResolver implements HandlerMethodArgumentResolver {

@Override

public boolean supportsParameter(MethodParameter parameter) {

return parameter.getParameterType().equals(ClientInfo.class);

}

@Override

public Object resolveArgument(MethodParameter parameter,

ModelAndViewContainer mavContainer,

NativeWebRequest webRequest,

WebDataBinderFactory binderFactory) {

HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();

ClientInfo client = new ClientInfo();

client.setIp(request.getRemoteAddr());

client.setUserAgent(request.getHeader("User-Agent"));

return client;

}

}

注册自定义解析器:

@Configuration

public class WebConfig implements WebMvcConfigurer {

@Override

public void addArgumentResolvers(List resolvers) {

resolvers.add(new ClientInfoArgumentResolver());

}

}

文件上传处理

处理multipart/form-data请求需要配置MultipartResolver:

@PostMapping("/upload")

public String handleFileUpload(

@RequestParam("file") MultipartFile file,

@RequestParam String description) {

if (!file.isEmpty()) {

String fileName = StringUtils.cleanPath(file.getOriginalFilename());

Path path = Paths.get("/uploads/" + fileName);

Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);

}

return "redirect:/success";

}

多文件上传处理:

@PostMapping("/multi-upload")

public String handleMultipleUpload(

@RequestParam("files") MultipartFile[] files) {

Arrays.stream(files).forEach(file -> {

// 处理每个文件

});

return "uploadResult";

}

参数类型转换

自定义类型转换器示例(将字符串转换为自定义Money类型):

public class MoneyConverter implements Converter {

@Override

public Money convert(String source) {

String[] parts = source.split(" ");

return new Money(new BigDecimal(parts[0]), Currency.getInstance(parts[1]));

}

}

注册转换器:

@Configuration

public class WebConfig implements WebMvcConfigurer {

@Override

public void addFormatters(FormatterRegistry registry) {

registry.addConverter(new MoneyConverter());

}

}

异步请求参数

在WebFlux环境中处理参数:

@PostMapping("/async")

public Mono> handleAsyncRequest(

@RequestBody Mono requestMono) {

return requestMono

.flatMap(request -> processRequest(request))

.map(response -> ResponseEntity.ok(response));

}

全局参数处理

使用@ControllerAdvice处理全局参数异常:

@ControllerAdvice

public class GlobalExceptionHandler {

@ExceptionHandler(MissingServletRequestParameterException.class)

public ResponseEntity handleMissingParams(MissingServletRequestParameterException ex) {

String error = ex.getParameterName() + " parameter is missing";

return ResponseEntity.badRequest().body(new ErrorResponse(error));

}

@ExceptionHandler(MethodArgumentTypeMismatchException.class)

public ResponseEntity handleTypeMismatch(MethodArgumentTypeMismatchException ex) {

String error = ex.getName() + " should be of type " + ex.getRequiredType().getSimpleName();

return ResponseEntity.badRequest().body(new ErrorResponse(error));

}

}

性能优化建议

避免在控制器方法中进行复杂参数处理

对高频请求接口进行参数缓存

使用适当的参数验证策略

对大型文件上传配置合理的临时存储位置

监控参数解析耗时

// 使用Filter进行前置参数验证示例

@Component

public class ParameterValidationFilter extends OncePerRequestFilter {

@Override

protected void doFilterInternal(HttpServletRequest request,

HttpServletResponse response,

FilterChain filterChain) throws ServletException, IOException {

if (requiresValidation(request)) {

// 执行自定义参数校验逻辑

if (invalidParametersDetected()) {

response.sendError(HttpStatus.BAD_REQUEST.value());

return;

}

}

filterChain.doFilter(request, response);

}

}