Spring Web开发
大约 6 分钟
Spring Web开发
Spring Web框架概述
Spring Web框架是Spring生态系统中用于构建Web应用程序的核心模块。它提供了完整的MVC架构支持,包括DispatcherServlet、控制器、视图解析、数据绑定、验证等功能。
Spring Web架构
Spring MVC核心组件
DispatcherServlet
DispatcherServlet是Spring MVC的核心前端控制器,负责接收所有HTTP请求并分发给相应的处理器:
// web.xml配置
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>控制器(Controller)
控制器负责处理用户请求并返回相应的模型和视图:
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
// 处理GET请求
@GetMapping
public String listUsers(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "user/list";
}
// 处理GET请求,返回用户详情
@GetMapping("/{id}")
public String getUser(@PathVariable Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "user/detail";
}
// 处理GET请求,显示创建表单
@GetMapping("/new")
public String showCreateForm(Model model) {
model.addAttribute("user", new User());
return "user/form";
}
// 处理POST请求,创建用户
@PostMapping
public String createUser(@Valid @ModelAttribute User user,
BindingResult result,
RedirectAttributes redirectAttributes) {
if (result.hasErrors()) {
return "user/form";
}
userService.save(user);
redirectAttributes.addFlashAttribute("message", "用户创建成功");
return "redirect:/users";
}
}RESTful Web服务
Spring MVC提供了强大的REST支持:
REST控制器
@RestController
@RequestMapping("/api/users")
public class UserRestController {
@Autowired
private UserService userService;
// 获取所有用户
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.findAll();
return ResponseEntity.ok(users);
}
// 根据ID获取用户
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.findById(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
// 创建用户
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
}
// 更新用户
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@Valid @RequestBody User user) {
user.setId(id);
User updatedUser = userService.update(user);
if (updatedUser != null) {
return ResponseEntity.ok(updatedUser);
} else {
return ResponseEntity.notFound().build();
}
}
// 删除用户
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}请求参数处理
@RestController
@RequestMapping("/api/search")
public class SearchController {
// 查询参数
@GetMapping("/users")
public List<User> searchUsers(@RequestParam(required = false) String name,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return userService.findByName(name, page, size);
}
// 请求头
@GetMapping("/info")
public String getInfo(@RequestHeader("User-Agent") String userAgent,
@RequestHeader(value = "Authorization", required = false) String auth) {
return "User-Agent: " + userAgent;
}
// Cookie
@GetMapping("/profile")
public String getProfile(@CookieValue("sessionId") String sessionId) {
return "Session ID: " + sessionId;
}
}数据绑定与验证
数据绑定
@Controller
public class FormController {
// 数据绑定到简单类型
@PostMapping("/simple")
public String handleSimple(@RequestParam String name,
@RequestParam int age) {
// 处理逻辑
return "result";
}
// 数据绑定到对象
@PostMapping("/user")
public String handleUser(@ModelAttribute User user) {
// Spring会自动将请求参数绑定到User对象的属性上
return "result";
}
// 数据绑定到嵌套对象
@PostMapping("/order")
public String handleOrder(@ModelAttribute Order order) {
// order.getUser().getName() 可以直接绑定
return "result";
}
}验证
// 实体类验证
public class User {
@NotNull(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")
private String name;
@NotNull(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 0, message = "年龄不能小于0")
@Max(value = 150, message = "年龄不能大于150")
private Integer age;
// getters and setters
}
@Controller
public class UserController {
@PostMapping("/users")
public String createUser(@Valid @ModelAttribute User user,
BindingResult result,
Model model) {
if (result.hasErrors()) {
// 验证失败,返回表单页面显示错误信息
return "user/form";
}
userService.save(user);
return "redirect:/users";
}
}自定义验证器
// 自定义验证注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneNumberValidator.class)
public @interface PhoneNumber {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 自定义验证器
public class PhoneNumberValidator implements ConstraintValidator<PhoneNumber, String> {
@Override
public boolean isValid(String phoneNumber, ConstraintValidatorContext context) {
if (phoneNumber == null) {
return true; // 让@NotNull处理空值
}
return phoneNumber.matches("^1[3-9]\\d{9}$");
}
}
// 使用自定义验证
public class User {
@PhoneNumber
private String phone;
// ...
}视图技术集成
Thymeleaf模板引擎
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
return resolver;
}
@Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
return engine;
}
@Bean
public ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("/WEB-INF/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}Thymeleaf模板示例
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>用户列表</title>
</head>
<body>
<h1>用户列表</h1>
<div th:if="${message}" class="alert alert-success" th:text="${message}"></div>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.email}"></td>
<td>
<a th:href="@{/users/{id}(id=${user.id})}" class="btn btn-info">查看</a>
<a th:href="@{/users/{id}/edit(id=${user.id})}" class="btn btn-primary">编辑</a>
</td>
</tr>
</tbody>
</table>
<a href="/users/new" class="btn btn-success">创建用户</a>
</body>
</html>异常处理
全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {
// 处理所有异常
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception e) {
ModelAndView mav = new ModelAndView("error");
mav.addObject("message", "系统发生错误: " + e.getMessage());
return mav;
}
// 处理特定异常
@ExceptionHandler(UserNotFoundException.class)
public ModelAndView handleUserNotFound(UserNotFoundException e) {
ModelAndView mav = new ModelAndView("error");
mav.addObject("message", "用户未找到: " + e.getUserId());
return mav;
}
// REST API异常处理
@ExceptionHandler(ValidationException.class)
@ResponseBody
public ResponseEntity<ErrorResponse> handleValidationException(ValidationException e) {
ErrorResponse error = new ErrorResponse("VALIDATION_ERROR", e.getMessage());
return ResponseEntity.badRequest().body(error);
}
}
// 错误响应类
public class ErrorResponse {
private String code;
private String message;
public ErrorResponse(String code, String message) {
this.code = code;
this.message = message;
}
// getters and setters
}文件上传
配置文件上传
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(10485760); // 10MB
resolver.setMaxInMemorySize(1048576); // 1MB
return resolver;
}
}文件上传控制器
@Controller
public class FileUploadController {
@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "请选择文件");
return "redirect:/uploadStatus";
}
try {
// 保存文件
byte[] bytes = file.getBytes();
Path path = Paths.get("uploads/" + file.getOriginalFilename());
Files.write(path, bytes);
redirectAttributes.addFlashAttribute("message",
"文件上传成功: " + file.getOriginalFilename());
} catch (IOException e) {
redirectAttributes.addFlashAttribute("message", "文件上传失败: " + e.getMessage());
}
return "redirect:/uploadStatus";
}
// RESTful文件上传
@PostMapping("/api/upload")
public ResponseEntity<String> handleFileUploadRest(@RequestParam("file") MultipartFile file) {
try {
// 处理文件上传逻辑
String fileName = fileService.saveFile(file);
return ResponseEntity.ok("文件上传成功: " + fileName);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("文件上传失败: " + e.getMessage());
}
}
}拦截器
自定义拦截器
@Component
public class LoggingInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
logger.info("请求开始: {} {}", request.getMethod(), request.getRequestURI());
request.setAttribute("startTime", System.currentTimeMillis());
return true; // 继续执行后续拦截器和处理器
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
logger.info("请求处理完成,耗时: {} ms", (endTime - startTime));
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
logger.info("请求结束: {} {}", request.getMethod(), request.getRequestURI());
if (ex != null) {
logger.error("请求处理异常", ex);
}
}
}注册拦截器
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoggingInterceptor loggingInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor)
.addPathPatterns("/api/**") // 拦截/api开头的请求
.excludePathPatterns("/api/public/**"); // 排除/api/public开头的请求
}
}跨域资源共享(CORS)
全局CORS配置
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}控制器级别CORS
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://localhost:3000")
public class UserRestController {
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
// 可以为特定方法设置不同的CORS配置
@CrossOrigin(origins = "http://admin.example.com")
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
}通过以上内容,我们可以全面了解Spring Web开发的各个方面,包括MVC架构、RESTful服务、数据绑定与验证、视图技术、异常处理、文件上传、拦截器和跨域处理等。Spring Web框架提供了完整的Web开发解决方案,能够满足各种复杂的Web应用需求。
