SpringBoot中的注解详解(一)
一、@RestController、@RequestMapping
1、@RestController注解
@RestController注解是SpringMVC中的一个组合注解,用于标记一个类为控制器类。它实际上是@Controller和@ResponseBody注解的组合,表示该类中的所有方法都会返回JSON、XML等格式的数据,而不是视图页面。
使用方式:
-
在需要处理HTTP请求的类上添加@RestController注解。
-
在类中定义处理HTTP请求的方法,并使用@RequestMapping或者其派生注解(如@GetMapping,@PostMapping等)来映射请求路径。
示例:
@RestController
@RequestMapping("/book")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping
public Result list(String keyword,
Integer categoryId){
List<Book> books = bookService.list(keyword, categoryId);
return Result.success(books);
}
@GetMapping("/{id}")
public Result get(@PathVariable("id") Integer id){
Book book = bookService.get(id);
return Result.success(book);
}
@PostMapping
public Result add(@RequestBody Book book){
bookService.add(book);
return Result.success();
}
@PutMapping
public Result update(@RequestBody Book book){
bookService.update(book);
return Result.success();
}
@DeleteMapping("/{ids}")
public Result delete(@PathVariable("ids") List<Integer> ids){
bookService.delete(ids);
return Result.success();
}
}
使用场景:
-
当需要创建RESTful API时,使用@RestController注解来标记控制器类。
-
适用于返回JSON、XML等数据格式的API开发。
-
通常放在项目的controller包下,与处理HTTP请求相关的类放在一起。
底层原理:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(annotation = Controller.class)
String value() default "";
}
-
@RestController
注解实际上是@Controller和@ResponseBody注解的组合。-
@Controller:标记该类为一个控制类,Spring容器会扫描并注册该类。
-
@ResponseBody:表示该类中的所有方法返回的数据都会直接写入HTTP响应体中,而不是解析为视图页面。
-
-
SpringMVC会使用RequestMappingHandlerMapping来扫描带有@Controller注解的类,并将这些类中的方法与URL映射起来。
-
当请求到达时,RequestMappingHandlerAdapter会调用相应的处理器方法,并将返回值转换为响应体中的数据。
@RestController
注解的底层原理:
-
Spring 容器启动:Spring 容器启动时,会扫描带有
@Configuration
注解的类。 -
解析
@Configuration
类中的@Bean
方法:解析这些类中的@Bean
方法,创建并注册 Bean 到容器。 -
扫描带有
@ComponentScan
的包:扫描配置中指定的包,发现带有@RestController
注解的类。 -
创建并注册 Controller 到容器:创建并注册这些 Controller 到容器。
-
创建代理对象:如果需要,创建代理对象以确保线程安全和依赖注入。
-
请求到达
DispatcherServlet
:当请求到达时,DispatcherServlet
会调用RequestMappingHandlerMapping
。 -
查找匹配的
HandlerMethod
:RequestMappingHandlerMapping
会查找匹配的HandlerMethod
。 -
调用
RequestMappingHandlerAdapter
:DispatcherServlet
调用RequestMappingHandlerAdapter
来执行 Controller 方法。 -
返回值处理:通过
@ResponseBody
注解,将返回值写入 HTTP 响应体。
2、@RequestMapping注解
@RequestMapping注解用于映射HTTP请求到控制器类或方法上。它可以放在类级别或方法级别,用于指定请求的URL路径、HTTP方法、请求参数等
使用方法:
-
在类级别使用@RequestMapping注解,指定该类的所有方法的公共路径前缀。
-
在方法级别使用@RequestMapping注解,指定具体的请求路径和HTTP方法。
@RestController
@RequestMapping("/book")
public class BookController {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Book getBook(@PathVariable Long id) {
// 处理获取书籍的逻辑
return new Book(id, "Spring Boot in Action");
}
@RequestMapping(method = RequestMethod.POST)
public Book createBook(@RequestBody Book book) {
// 处理创建书籍的逻辑
return book;
}
}
使用场景:
-
当需要将HTTP请求映射到控制器类或方法上时,使用@RequestMapping注解。
-
适用于处理各种HTTP方法(GET、POST、PUT、DELETE 等)的请求。
-
通常放在控制器类或方法上,与处理HTTP请求相关的类和方法放在一起。
底层原理:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
-
@RequestMapping注解被RequestMappingHandlerMapping处理,该类负责将请求URL映射到相应的控制器方法。
-
@RequestMappingHandlerMapping会扫描带有@Controller注解的类,并将这些类中的方法与URL映射起来。
-
当请求到达时,DispatcherServlet会根据请求URL和HTTP方法找到对应的处理器方法,并调用RequestMappingHandlerAdapter来执行该方法。
-
RequestMappingHandlerAdapter会处理方法参数的绑定、方法的调用以及返回值的处理。
@RequestMapping
注解的底层原理:
-
请求到达
DispatcherServlet
:当请求到达时,DispatcherServlet
会调用RequestMappingHandlerMapping
。 -
查找匹配的
HandlerMethod
:RequestMappingHandlerMapping
会查找匹配的HandlerMethod
,首先匹配类级别的@RequestMapping
,然后匹配方法级别的@RequestMapping
。 -
找到匹配的
HandlerMethod
:找到匹配的HandlerMethod
后,DispatcherServlet
调用RequestMappingHandlerAdapter
。 -
调用 Controller 方法:
RequestMappingHandlerAdapter
调用 Controller 方法,处理方法参数(如@PathVariable
,@RequestBody
等)。 -
执行 Controller 方法:执行 Controller 方法。
-
返回值处理:通过
@ResponseBody
注解,将返回值写入 HTTP 响应体。
总结:
-
@RestController
注解:-
功能:标记一个类为控制器类,所有方法返回 JSON、XML 等数据。
-
使用方式:在类上添加
@RestController
注解,类中定义处理 HTTP 请求的方法。 -
使用场景:创建 RESTful API,返回数据格式的 API 开发。
-
放置位置:通常放在
controller
包下。 -
底层原理:组合了
@Controller
和@ResponseBody
注解,Spring MVC 会扫描并注册该类,处理请求并返回数据。
-
-
@RequestMapping
注解:-
功能:映射 HTTP 请求到控制器类或方法上。
-
使用方式:在类或方法上添加
@RequestMapping
注解,指定请求路径和 HTTP 方法。 -
使用场景:处理各种 HTTP 方法的请求。
-
放置位置:通常放在控制器类或方法上。
-
底层原理:被
RequestMappingHandlerMapping
处理,将请求 URL 映射到相应的控制器方法,DispatcherServlet
调用RequestMappingHandlerAdapter
执行方法。
-
二、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping("/{ids}")
1、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping("/{ids}") (Controller层)
注解概述:
-
注解类型:这些注解属于Spring框架中的控制器注解,用于定义HTTP请求映射。
-
功能:
-
@GetMapping:映射HTTP GET请求到特定的处理方法上。
-
@PostMapping
:映射HTTP POST请求到特定的处理方法上。 -
@PutMapping
:映射HTTP PUT请求到特定的处理方法上。 -
@DeleteMapping
:映射HTTP DELETE请求到特定的处理方法上。
-
-
使用方法:这些注解通常用于SpringMVC或SpringBoot的控制器类中的方法上,以指定该方法处理HTTP请求类型和路径。
使用场景:
-
@GetMapping:适用于获取资源信息的场景,如查询数据。
-
@PostMapping:适用于创建新资源的场景,如提交表单数据。
-
@PutMapping:适用于更新现有资源的场景,如修改用户信息。
-
@DeleteMapping:适用于删除资源的场景,如删除用户记录。
-
这些注解应放置在控制器类的方法上,通常用于@Controller或@RestController注解的类中。
底层原理:
-
注解解析:Spring框架在启动时会扫描带有
@Controller
或@RestController
注解的类,并解析其中的方法上的这些注解。 -
请求映射:Spring MVC通过
RequestMappingHandlerMapping
将这些注解映射到具体的处理器方法上。 -
请求处理:当接收到HTTP请求时,Spring MVC会根据请求的URL和HTTP方法找到对应的处理器方法,并调用该方法处理请求。
小结:
-
类型:方法注解
-
位置:基于SpringMVC的RESTful开发控制器方法定义上方
-
作用:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求
-
动作,例如@GetMapping对应GET请求
-
属性:value(默认):请求访问路径
2、@PathVariable、@RequestBody 、@RequestParam、
@PathVariable:
-
功能:用于从URL模板中提取变量值,并将其绑定到方法参数上。
-
使用场景:适用于需要从URL路径中获取动态部分的场景,如获取某个用户的详细信息。
-
作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
-
用于从URL路径中获取数据,通常用于处理RESTful风格的请求。
可以将URL中的占位符部分提取为方法参数,用于标识资源的唯一标识符。
可以指定参数名称、正则表达式等属性。
适用于获取URL中的动态参数,如用户ID、商品ID等。
示例: @GetMapping("/users/{id}") public String getUser(@PathVariable("id") int userId) { ... }
@RequestBody:
-
功能:用于将HTTP请求体中的数据绑定到方法的参数上。
-
使用场景:适用于需要接收客户端发送的JSON、XML等格式的数据的场景,如创建或更新资源
-
作用:将JSON数据映射到形参的实体类对象中,
设置控制器方法返回值作为响应体返回给客户端,无需解析,Spring MVC会将返回的对象转换为JSON格式的响应体,并设置正确的响应头
-
适用于处理复杂的数据结构,可以将请求体中的数据映射到对象或集合类型的参数上。
示例: @PostMapping("/users") public String createUser(@RequestBody User user) { ... }
@RequestParam:
-
功能:用于从HTTP请求的查询参数中提取值,并将其绑定到方法参数上。
-
使用场景:适用于需要从URL查询参数中获取值的场景,如分页查询
-
用于从请求参数中获取数据,通常用于处理GET请求或POST请求的表单数据。
可以获取请求URL中的查询参数或POST请求中的表单参数。
可以指定参数名称、是否必需、默认值等属性。
适用于获取简单的请求参数,如字符串、数字等。
示例: @GetMapping("/users") public String getUser(@RequestParam("id") int userId) { ... }
/**
* 根据书籍 ID 获取书籍详情。
* @param id 从 URL 中提取书籍 ID
* @return 返回包含书籍详情的 Result 对象
*/
@GetMapping("/{id}") // 映射 GET 请求到该方法,路径参数为 id
public Result get(@PathVariable("id") Integer id){
Book book = bookService.get(id);
return Result.success(book);
}
// 更新书籍信息
// @RequestBody:从请求体中读取 Book 对象
@PutMapping
public Result update(@RequestBody Book book){
bookService.update(book);
return Result.success();
}
/**
* 用于处理分页查询请求
* 指定了该方法处理HTTP GET请求,并且要求请求中必须包含pageNum 和 pageSize两个查询参数
* @param pageNum 请求的页码,从请求的查询参数中提取名为pageNum的参数,并将其绑定到方法参数pageNum上
* @param pageSize 页的大小,从请求的查询参数中提取名为pageSize的参数,并将其绑定到方法参数pageSize上
* @param publisher 出版社信息,从请求的查询参数中提取名为publisher的参数,并将其绑定到方法参数publisher上
* @return : 将查询结果封装到Result对象中,并返回给客户端。
*/
@GetMapping(params = {"pageNum", "pageSize"})
public Result pageQuery(@RequestParam("pageNum") int pageNum,
@RequestParam("pageSize") int pageSize,
@RequestParam("publisher") String publisher){
// 调用bookService的pageQuery方法,传入分页参数和版本社名称,获取分页查询结果
Page<Book> page = bookService.pageQuery(pageNum, pageSize, publisher);
return Result.success(page);
}
请简述@RequestBody @RequestParam @PathVariable的区别
-
3个注解它们都是Spring MVC框架中常用的注解,用于从HTTP请求中获取数据。
-
@RequestParam 用于获取请求参数中的数据, @RequestBody 用于获取请求体中的数据, @PathVariable 用于获取URL路径中的数据 。
-
它们分别适用于不同的场景和数据来源,可以根据具体的业务需求选择适合的注解来获取HTTP请求中的数据。
三、@RestControllerAdvice、@ExceptionHandler(Exception.class) (exception包)
@RestControllerAdvice:
-
功能:用于定义全局异常类,可以处理所有带有
@Controller
或@RestController
注解的控制器类中抛出的异常。 -
使用场景:统一处理应用中所有控制器的异常,提供一致的错误响应格式。
-
类型: 类注解
-
位置:Rest风格开发的控制器增强类定义上方
-
作用:为Rest风格开发的控制器类做增强
-
说明:此注解自带@ResponseBody注解与@Component注解,具备对应的功能
@ExceptionHandler(Exception.class) :
-
功能:用于定义处理特定异常的方法,方法参数为需要处理的异常类型。
-
使用方法:放置在方法声明上,方法参数为需要处理的异常类型。
-
使用场景:适用于需要针对异常类型进行处理的场景。
-
通常放置在@RestControllerAdvice注解的类中的方法上。
-
类型: 方法注解
-
位置:专用于异常处理的控制器方法上方
-
作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行
-
说明:此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常
package com.briup.demo.exception;
import com.briup.demo.response.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @author 35329
*
* 全局处理异常处理器
*
* 两大作用:
* 1)统一对Controller中抛出的业务异常进行
* 降低代码的冗余。
* 2)程序中可能出现的异常到返回给前端之前的最后一道屏障。
* 能够正常提供服务的最后一道屏障。
* 控制程序不会直接向前端返回内部的逻辑错误。
*
* 具体的实施方法
* 1、在类上添加注解:@RestControllerAdvice
* 添加了该注解之后,在这个类中方法的返回值就和Controller中的方法一样
* 直接作为返回前端的响应报文体部的数据
*
* 2、定义一个统一处理异常的方法
* 在该方法上添加该注解:@ExceptionHandler
* 在改注解中配置value属性值,指定要拦截的异常类型。
* 实际开发中,通常都会设置为异常体系的最高级别类型:Exception
*
* 如果需要对异常对象进行直接处理
* 可以在方法中定义一个Exception类型的参数,
* 只要我们定义了这个参数,Spring框架在调用该方法的时候,
* 就会把底层上抛的异常作为参数传递
*
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result handle(Exception e){
// 需要对异常的具体类型进行判断:
// 1、对自己主动抛出的业务类型异常
// 2、其他所有未知的运行时异常
if (e instanceof BookException){
return Result.failure(e.getMessage());
}
return Result.failure("服务器繁忙,请稍后重试");
}
}