本文收录于《滚雪球学Spring》专栏,手把手带你零基础教学Spring,从入门到就业,助你早日登顶实现财富自由;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
在上一期【5.1 Spring MVC架构】中,我们深入分析了Spring MVC的整体架构与核心工作流程,包括DispatcherServlet
、HandlerMapping
、ViewResolver
等组件如何协同工作,帮助开发者高效处理用户请求并生成响应。我们还探讨了Spring MVC如何通过这种架构模式简化Web应用开发中的复杂流程。在此基础上,开发者开始面临另一个常见问题:如何优雅地处理Web请求,如何简洁、灵活地定义控制器和绑定请求参数?Spring MVC提供了一系列的注解,使得这一切变得更加简单和直观。
本期【5.2 注解驱动的Spring MVC】将聚焦于Spring MVC的注解使用,特别是@Controller
与@RequestMapping
、参数绑定与类型转换、以及表单处理与数据校验(JSR-303/JSR-380)。通过使用这些注解,开发者可以大大简化代码结构,并增强控制器的可读性和灵活性。我们会通过具体示例深入探讨这些注解的实际应用,帮助读者更好地理解和掌握注解驱动开发的优势。
@Controller
是Spring MVC中最基本的注解之一,用于定义控制器类。控制器是Spring MVC的核心组件,负责接收用户请求,执行业务逻辑,并返回视图或数据。通过@Controller
,Spring会将这个类自动注册为一个控制器,并将其纳入Spring上下文中。
@Controller
public class HomeController {
@RequestMapping("/home")
public String home() {
return "home";
}
}
在这个例子中,HomeController
被标记为一个控制器,@RequestMapping("/home")
注解表明home()
方法将处理所有访问/home
路径的请求。方法的返回值是视图名称(如home.jsp
)。
@RequestMapping
是Spring MVC中的另一个重要注解,用于将URL请求映射到具体的处理方法。通过这个注解,我们可以定义哪些控制器方法处理哪些URL路径,甚至可以指定请求方法类型(如GET、POST、PUT等)。
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String showCreateForm(Model model) {
model.addAttribute("user", new User());
return "createUser";
}
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String submitCreateForm(@ModelAttribute User user) {
userService.save(user);
return "redirect:/user/list";
}
}
在这个示例中,showCreateForm
方法处理GET请求,用于显示创建用户的表单;而submitCreateForm
处理POST请求,接收用户提交的表单数据并保存。
Spring MVC还支持为一个方法映射多个路径,并为不同的请求类型设置不同的处理逻辑。例如,我们可以通过一个控制器处理多个不同的请求路径:
@RequestMapping(value = {"/user/add", "/admin/user/add"}, method = {RequestMethod.POST, RequestMethod.PUT})
public String addUser() {
// 添加用户逻辑
return "success";
}
通过@RequestMapping
和@RestController
注解,Spring MVC非常适合构建REST风格的API。@RestController
是@Controller
和@ResponseBody
的组合,用于简化RESTful API的开发。
@RestController
@RequestMapping("/api/products")
public class ProductApiController {
@GetMapping("/{id}")
public Product getProduct(@PathVariable Long id) {
return productService.getProductById(id);
}
@PostMapping
public Product createProduct(@RequestBody Product product) {
return productService.saveProduct(product);
}
}
在这个例子中,通过@RestController
,我们可以轻松构建一个REST API,用于获取产品信息和创建新产品。
Spring MVC支持通过注解直接将HTTP请求的参数(如查询参数、表单数据)自动绑定到控制器的方法参数上。常用的注解包括@RequestParam
和@PathVariable
,它们分别用于绑定查询参数和路径变量。
@Controller
@RequestMapping("/product")
public class ProductController {
@RequestMapping("/search")
public String searchProduct(@RequestParam("keyword") String keyword, Model model) {
List<Product> products = productService.search(keyword);
model.addAttribute("products", products);
return "productList";
}
@RequestMapping("/{id}")
public String getProductDetails(@PathVariable("id") Long id, Model model) {
Product product = productService.getProductById(id);
model.addAttribute("product", product);
return "productDetails";
}
}
@RequestParam
用于绑定请求参数中的keyword
。@PathVariable
用于绑定URL中的路径变量id
。Spring MVC支持将请求参数从字符串类型自动转换为指定的目标类型,如从String
转换为Integer
、Date
等。Spring MVC内置了一些常见的类型转换器,但我们也可以通过自定义转换器实现更加复杂的类型转换需求。
@Component
public class StringToDateConverter implements Converter<String, Date> {
private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date convert(String source) {
try {
return formatter.parse(source);
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date format");
}
}
}
在这个示例中,自定义的StringToDateConverter
用于将字符串转换为Date
类型。
@InitBinder
是Spring MVC中用于定制数据绑定的注解。我们可以通过@InitBinder
对数据的绑定过程进行细粒度的控制,特别适用于日期、时间等复杂数据类型的绑定。
@Controller
@RequestMapping("/event")
public class EventController {
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
@RequestMapping("/create")
public String createEvent(@RequestParam("eventDate") Date eventDate, Model model) {
model.addAttribute("eventDate", eventDate);
return "eventDetails";
}
}
通过@InitBinder
,我们可以灵活地自定义日期的格式化方式,从而将请求参数eventDate
从String
自动转换为Date
类型。
Spring MVC中的表单处理非常简单。通过@ModelAttribute
注解,表单提交的数据可以自动映射到控制器方法的参数对象上。这样开发者可以避免手动从请求参数中提取数据,极大地简化了代码。
@Controller
@RequestMapping("/register")
public class RegistrationController {
@GetMapping
public String showForm(Model model) {
model.addAttribute("user", new User());
return "registerForm";
}
@PostMapping
public String submitForm(@ModelAttribute User user, BindingResult result, Model model) {
if (result.hasErrors()) {
return "registerForm";
}
userService.saveUser(user);
return "redirect:/register/success";
}
}
在这个示例中:
@ModelAttribute
自动将表单数据绑定到User
对象上。BindingResult
用于捕获和处理表单校验错误,如果有错误,会重新返回表单页面。JSR-303和JSR-380是Java中的数据校验标准。Spring MVC与Hibernate Validator集成后,可以通过注解的方式声明数据校验规则,极大简化了表单数据的校验。
@Entity
public class User {
@NotNull
@Size(min = 2, max = 30)
private String name;
@NotNull
@Email
private String email;
// getters and setters
}
@NotNull
:确保字段不能为空。@Size
:限制字符串的长度。@Email
:确保字段为合法的电子邮件地址。在控制器中,我们可以使用@Valid
注解触发对象的校验,同时使用BindingResult
对象获取校验结果。如果校验失败,则返回表单页面。
@Controller
@RequestMapping("/register")
public class RegistrationController {
@PostMapping
public String submitForm(@Valid @ModelAttribute User user, BindingResult result, Model model) {
if (result.hasErrors()) {
return "registerForm";
}
userService.saveUser(user);
return "redirect:/register/success";
}
}
在这个示例中,@Valid
注解用于触发校验,而BindingResult
则捕获校验结果并处理错误。
除了使用JSR-303/JSR-380的内置校验注解外,开发者还可以通过自定义校验器来实现更复杂的业务逻辑校验。
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
public @interface UniqueEmail {
String message() default "Email already exists";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Autowired
private UserService userService;
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
return userService.isEmailUnique(email);
}
}
通过自定义注解@UniqueEmail
,我们可以实现复杂的校验逻辑,如检查用户邮箱的唯一性。
在某些场景下,我们可能希望根据不同的操作(如创建和更新)使用不同的校验规则。Spring MVC支持使用分组校验,通过@Validated
注解指定校验分组。
public class User {
@NotNull(groups = CreateGroup.class)
private String name;
@NotNull(groups = UpdateGroup.class)
private String email;
}
通过为不同字段指定不同的校验组,可以在控制器中使用不同的校验规则。
在表单中,可能会涉及到嵌套对象的校验,Spring MVC支持级联校验,即当一个对象包含其他对象时,校验会递归地验证所有嵌套的对象。
@Entity
public class Order {
@NotNull
@Valid
private User user;
}
在这个示例中,@Valid
注解会触发对User
对象的递归校验,确保所有嵌套对象的校验规则都被执行。
这篇文章横向深入讲解了Spring MVC的注解驱动开发,提供了全面的@Controller
、@RequestMapping
的使用方法,详细介绍了参数绑定、类型转换的实现,重点探讨了JSR-303/JSR-380数据校验的标准与自定义校验。通过具体的案例,文章帮助读者掌握了如何利用Spring MVC的注解机制简化控制器的开发,提升代码的可读性与维护性。
通过本期【5.2 注解驱动的Spring MVC】,我们详细探讨了Spring MVC中的注解使用,特别是@Controller
、@RequestMapping
、参数绑定、类型转换以及表单处理与数据校验的实现方式。通过具体的案例,展示了如何简化控制器的开发,并实现高效的表单校验。
在下一期【5.3 视图层的选择】中,我们将讨论Spring MVC中视图层的不同选择,包括Thymeleaf、JSP、FreeMarker和Velocity,帮助开发者根据项目需求选择合适的视图技术。
无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学Spring」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门Spring,就像滚雪球一样,越滚越大, 无边无际,指数级提升。
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。
-End-