滚雪球学Spring[5.2讲]:注解驱动的Spring MVC

本文收录于《滚雪球学Spring》专栏,手把手带你零基础教学Spring,从入门到就业,助你早日登顶实现财富自由;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

全文目录:

  • 前言
  • 5.2 注解驱动的Spring MVC
    • 1. @Controller与@RequestMapping
      • 1.1 @Controller注解
        • 示例:定义一个简单的控制器
      • 1.2 @RequestMapping注解
        • 示例:处理GET和POST请求
        • 多个路径与请求方法映射
      • 1.3 REST风格支持
        • 示例:构建REST API
    • 2. 参数绑定与类型转换
      • 2.1 参数绑定
        • 示例:绑定查询参数和路径变量
      • 2.2 类型转换
        • 示例:自定义类型转换器
      • 2.3 @InitBinder注解
        • 示例:使用@InitBinder定制数据绑定
    • 3. 表单处理与数据校验(JSR-303/JSR-380)
      • 3.1 表单处理
        • 示例:表单提交与处理
      • 3.2 JSR-303/JSR-380数据校验
        • 示例:使用JSR-303进行数据校验
      • 3.3 控制器中处理校验结果
        • 示例:处理数据校验结果
      • 3.4 自定义校验器
        • 示例:自定义邮箱唯一性校验
    • 4. 扩展内容:数据校验的高级用法
      • 4.1 分组校验
        • 示例:分组校验
      • 4.2 级联校验
        • 示例:级联校验
    • 总结
    • 下期预告
  • 福利赠与你
  • ✨️ Who am I?

前言

在上一期【5.1 Spring MVC架构】中,我们深入分析了Spring MVC的整体架构与核心工作流程,包括DispatcherServletHandlerMappingViewResolver等组件如何协同工作,帮助开发者高效处理用户请求并生成响应。我们还探讨了Spring MVC如何通过这种架构模式简化Web应用开发中的复杂流程。在此基础上,开发者开始面临另一个常见问题:如何优雅地处理Web请求,如何简洁、灵活地定义控制器和绑定请求参数?Spring MVC提供了一系列的注解,使得这一切变得更加简单和直观。

本期【5.2 注解驱动的Spring MVC】将聚焦于Spring MVC的注解使用,特别是@Controller@RequestMapping、参数绑定与类型转换、以及表单处理与数据校验(JSR-303/JSR-380)。通过使用这些注解,开发者可以大大简化代码结构,并增强控制器的可读性和灵活性。我们会通过具体示例深入探讨这些注解的实际应用,帮助读者更好地理解和掌握注解驱动开发的优势。

5.2 注解驱动的Spring MVC

1. @Controller与@RequestMapping

1.1 @Controller注解

@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)。

1.2 @RequestMapping注解

@RequestMapping 是Spring MVC中的另一个重要注解,用于将URL请求映射到具体的处理方法。通过这个注解,我们可以定义哪些控制器方法处理哪些URL路径,甚至可以指定请求方法类型(如GET、POST、PUT等)。

示例:处理GET和POST请求
@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";
}

1.3 REST风格支持

通过@RequestMapping@RestController注解,Spring MVC非常适合构建REST风格的API。@RestController@Controller@ResponseBody的组合,用于简化RESTful API的开发。

示例:构建REST 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,用于获取产品信息和创建新产品。

2. 参数绑定与类型转换

2.1 参数绑定

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

2.2 类型转换

Spring MVC支持将请求参数从字符串类型自动转换为指定的目标类型,如从String转换为IntegerDate等。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类型。

2.3 @InitBinder注解

@InitBinder是Spring MVC中用于定制数据绑定的注解。我们可以通过@InitBinder对数据的绑定过程进行细粒度的控制,特别适用于日期、时间等复杂数据类型的绑定。

示例:使用@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,我们可以灵活地自定义日期的格式化方式,从而将请求参数eventDateString自动转换为Date类型。

3. 表单处理与数据校验(JSR-303/JSR-380)

3.1 表单处理

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用于捕获和处理表单校验错误,如果有错误,会重新返回表单页面。

3.2 JSR-303/JSR-380数据校验

JSR-303和JSR-380是Java中的数据校验标准。Spring MVC与Hibernate Validator集成后,可以通过注解的方式声明数据校验规则,极大简化了表单数据的校验。

示例:使用JSR-303进行数据校验
@Entity
public class User {

    @NotNull
    @Size(min = 2, max = 30)
    private String name;

    @NotNull
    @Email
    private String email;

    // getters and setters
}
  • @NotNull:确保字段不能为空。
  • @Size:限制字符串的长度。
  • @Email:确保字段为合法的电子邮件地址。

3.3 控制器中处理校验结果

在控制器中,我们可以使用@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则捕获校验结果并处理错误。

3.4 自定义校验器

除了使用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,我们可以实现复杂的校验逻辑,如检查用户邮箱的唯一性。

4. 扩展内容:数据校验的高级用法

4.1 分组校验

在某些场景下,我们可能希望根据不同的操作(如创建和更新)使用不同的校验规则。Spring MVC支持使用分组校验,通过@Validated注解指定校验分组。

示例:分组校验
public class User {

    @NotNull(groups = CreateGroup.class)
    private String name;

    @NotNull(groups = UpdateGroup.class)
    private String email;
}

通过为不同字段指定不同的校验组,可以在控制器中使用不同的校验规则。

4.2 级联校验

在表单中,可能会涉及到嵌套对象的校验,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文档等海量资料。

✨️ Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

滚雪球学Spring[5.2讲]:注解驱动的Spring MVC_第1张图片

-End-

你可能感兴趣的:(#,滚雪球学Spring,spring,mvc,java,注解,Spring,MVC)