文章目录
- 一、元注解
-
- 1.1 @Target:
- 1.2 @Retention:
- 二、常见注解
-
- 2.1 @Controller:
- 2.2 @SpringBootApplication:
- 2.3 @RequestMapping:
- 2.4 @RequestParam:
- 2.5 @PathVariable:
- 2.6 @RequestPart:
- 2.7 @RequestBody:
- 2.8 @RequestHeader:
- 2.9 @ResponseStatus:
- 2.10 @ResponseBody:
- 三、获取Cookie / Session
-
- 3.1 获取 Cookie:
-
- 3.1.1 传统的获取方式:
- 3.1.2 通过注解获取(@CookieValue):
- 3.2 获取 Session:
-
- 3.2.1 传统的获取方式:
- 3.2.2 通过注解获取(@SessionAttribute):
学习 Spring MVC,其实就是学习各种 Web 开发需要用到的注解。
下图是各个注解的作用简述,友友可以根据自己需要,查阅相应的注解用法。
一、元注解
在 Spring 框架中,元注解指的是可以用来注解其他注解的注解。这个非常重要,学习了他们,通过观察一个注解的元注解,就能明白 spring 注解的部分重要属性。
1.1 @Target:
@Target:表示注解使用的位置。
常见的 @Target 参数如下:
ElementType.TYPE:表示注解可以应用于类、接口(包括注解类型)或枚举类型的声明上。
ElementType.METHOD:表示注解可以使用在方法声明上。
ElementType.PARAMETER:表示注解可以使用在方法参数的声明上。
1.2 @Retention:
@Retention:表示注的声明周期。
常见的 @Retention 参数如下:
RetentionPolicy.SOURCE:表示注解只在源代码级别保留,不会被编译到字节码文件中。
RetentionPolicy.CLASS:表示注解在编译后的字节码文件中保留,但在运行时由 JVM 加载类时会被丢弃。
RetentionPolicy.RUNTIME:表示注解在运行时仍然保留,可以通过反射机制进行访问。
二、常见注解
2.1 @Controller:
- 作用:
只有被 @Controller 注解标识的类,才会被 Spring 程序调用到。
- 使用位置:
@Target({ElementType.TYPE})
通过观察元注解可以得知,这是一个类注解。
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
作用生命周期,在程序未结束之前一直存在。
- @Controller 和 @RestController 的关系:
@RestController 可以等价为 @Controller 和 @ResponseBody 配合使用。
下图为 @RestController 的部分源码。
也就是说最开始返回的都是视图类数据,不过 spring 对其进行了封装,使其能够返回各类数据。
- @Controller 和 @RestController 的区别:
被 @Controller 标识的方法的返回值通常是视图名称或 ModelAndView 对象,用于决定要渲染的视图页面。(如果方法返回值是一个对象,且该方法上没有添加 @ResponseBody 注解,Spring 会将其视为视图名称,并尝试查找对应的视图进行渲染。)
被 @RestController 标识的方法的返回值会被直接序列化为指定的格式(如 JSON | HTML 等)并写入 HTTP 响应体中。
可以简单理解为:
@Controller:用来返回视图数据之类的。
@RestController:用来返回除视图外的各类数据。
为了更加方便友友们理解,下面给出二者使用区别的效果图。
演示代码:
@Controller
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param1")
@ResponseBody
public String param1(){
return "/index.html";
}
@RequestMapping("/param2")
public String param2(){
return "/index.html";
}
}
效果:
2.2 @SpringBootApplication:
- 作用:
这个注解是 Spring Boot 项目的基石,创建 SpringBoot 项目之后会默认在主类加上。
@SpringBootApplication 是一个组合注解,没有它 spring 程序就启动不了,被@SpringBootApplication
修饰的类,我们一般称为启动类。
组合注解内容:
-
@SpringBootConfiguration
:表明这是一个 Spring Boot 的配置类,类似于传统 Spring 中的@Configuration
注解,用于定义 Spring 容器的 Bean 配置信息。 -
@EnableAutoConfiguration
:启用自动配置功能。Spring Boot 会根据项目依赖自动配置 Spring 应用程序上下文,例如自动配置数据源、Web 服务器等组件,减少了手动配置的工作量。 -
@ComponentScan
:扫描当前包及其子包下被@Component
、@Service
、@Repository
、@Controller
等注解标记的类,并将它们注册到 Spring 容器中。
@SpringBootApplication
注解简化了 Spring Boot 应用程序的开发,使得开发者能够更加专注于业务逻辑的实现。
- 使用位置:
@Target({ElementType.TYPE})
类注解。
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
2.3 @RequestMapping:
- 作用:
@RequestMapping 来实现 URL 路由映射,也就是浏览器连接程序的作用。
- 使用位置:
@Target({ElementType.TYPE, ElementType.METHOD})
既可修饰类,也可以修饰方法。
当修饰类和方法时,访问的地址是类路径+方法路径。
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 支持的请求方法:
@RequestMapping 默认支持所有的请求。
如果想要指定接收 GET 或者其它请求。
我们可以显示的指定 @RequestMapping 来接收 POST 的情况,如下所示:
@Controller
@ResponseBody
@RequestMapping("/request")
public class RequestController {
@RequestMapping(value = "/param1",method = RequestMethod.POST)
public String param1(){
return "我只支持 POST 请求";
}
}
上面的请求是通过 postman 构造的,关于 postman 如何安装使用,这里就不做介绍,有需要的友友网上查一下。
@RequestMapping 是使用的最多的注解之一,所以下面会对其源码的属性进行讲解。
- @RequestMapping 注解属性分析:
下面为 @RequestMapping 注解的源码。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective({ControllerMappingReflectiveProcessor.class})
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 {};
}
- name:
用途:主要用于为映射指定一个有意义的名称。
- value(或 path):
这两个注解头上都带有 @AliasFor 注解(起别名),且注解里面都带有对方的名字,说明这两个注解的作用是一样的。
用途:用于指定要映射的请求路径。
示例:@RequestMapping(value = "/users")
或@RequestMapping(path = "/users")
,表示将该注解标注的方法映射到/users
路径的请求上。
- method:
用途:指定处理的 HTTP 方法类型,如 GET、POST、PUT、DELETE 等。
示例:@RequestMapping(value = "/users", method = RequestMethod.GET)
表示只处理 GET 请求到/users
路径的请求。
- params:
用途:指定请求必须包含的参数或者特定的参数值。
示例:@RequestMapping(value = "/users", params = "id=123")
表示只有当请求中包含参数id
且值为123
时才会匹配该映射。
- headers:
用途:指定请求必须包含的特定 HTTP 头信息。
示例:@RequestMapping(value = "/users", headers = "Authorization=Bearer xxx")
表示只有当请求头中包含指定的授权信息时才会匹配该映射。
- consumes:
用途:指定处理请求的内容类型(Content-Type),用于限制请求的输入格式。
示例:@RequestMapping(value = "/users", consumes = "application/json")
表示只处理内容类型为 JSON 的请求。
- produces:
用途:指定响应的内容类型,用于告知客户端响应的格式。
示例:@RequestMapping(value = "/users", produces = "application/json")
表示响应的内容类型为 JSON。
注意:注解参数没有写名称,默认传输给 value。例如,@RequestMapping("/users")
等同于@RequestMapping(value = "/users")
。
2.4 @RequestParam:
- 作用:
绑定请求参数到方法参数。
某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个 time 给后端,而后端是使用createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用 @RequestParam 来重命名前后端的参数值。
- 使用位置:
下面这张图的意思,在文章最上面的元注解,已经解释的很清楚了,这里就不再赘述。
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param2")
public String param2(@RequestParam("time") String createtime){
return "接收到的参数为: " + createtime;
}
}
注意点:
- 使用 @RequestParam 进行参数重命名时,请求参数只能和 @RequestParam 声明的名称一致,才能进行参数绑定和赋值。原来方法的参数名称作废。
- 使用 @RequestParam 进行参数重命名时,参数就变成了必传参数(可以通过 required 属性进行修改)。
2.5 @PathVariable:
- 作用:
获取 URL 中参数。
- 使用位置:
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param3/{id}/{userName}")
public String param3(@PathVariable("id") String id,@PathVariable("userName") String name){
return "id: " + id + " userName: " + name;
}
}
2.6 @RequestPart:
- 作用:
一般用来接收文件。
- 使用位置:
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param4")
public String param4(@RequestPart("text") MultipartFile file) throws IOException {
//获取文件名称
String fileName = file.getOriginalFilename();
//上传文件到指定路径
file.transferTo(new File("D:/test/" + fileName));
return "接收到的名称为: " + fileName;
}
}
下图是使用 postman 来构造请求的。
文件也成功传输到了指定位置,由于不好展示,所以就没有贴出来。
2.7 @RequestBody:
- 作用:
该注解通常用于将 HTTP 请求的主体内容绑定到方法的参数上。它指示 Spring 将请求体中的数据转换为指定的 Java 对象,以便在控制器方法中进行处理。
简单来说:在方法参数上加上这个注解,才能获取到 JSON 对象。
- 使用位置:
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/Json")
public String getJson(@RequestBody UserInfo info){
return "接收到的参数为: " + info;
}
}
2.8 @RequestHeader:
- 作用:
用于获取 HTTP 请求头中的信息。
- 使用位置:
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/header")
public String getHeader(@RequestHeader("User-Agent") String userAgent){
return "userAgent: " + userAgent;
}
}
2.9 @ResponseStatus:
- 作用:
设置状态值。
- 使用位置:
@Target({ElementType.TYPE, ElementType.METHOD})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/status")
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String setStatus(String status){
return "我是400,但是我能正常访问";
}
}
2.10 @ResponseBody:
这个在上面 @Controller 已经有涉及到,这里再做些补充。
- 作用:
主要用于将控制器方法的返回值直接作为 HTTP 响应体返回给客户端,而不是将其解析为视图名称进行页面渲染。
- 使用位置:
@Target({ElementType.TYPE, ElementType.METHOD})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
由于上面已经演示过关于 @ResponseBody 注解的区别,所以这里不再进行演示。
三、获取Cookie / Session
操作 Cookie 和 Session 的方式不一定要采取注解的方式,但是由于注解将原始的获取方式进行封装,所以将其添加到本文章中。
3.1 获取 Cookie:
3.1.1 传统的获取方式:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param5")
public String param5(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie:cookies){
System.out.println(cookie.getName() + ": " + cookie.getValue());
}
}
return "打印 Cookie 成功";
}
}
Spring MVC 是基于 Servlet API 构建的原始 Web 框架,也是在 Servlet 的基础上实现的。
HttpServletRequest,HttpServletResponse 是 Servlet 提供的两个类,是 Spring MVC 方法的内置对象。需要时直接在方法中添加声明即可。
HttpServletRequest 对象代表客户端的请求,当客户端通过 HTTP 协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
HttpServletResponse 对象代表服务器的响应。HTTP 响应的信息都在这个对象中,比如向客户端发送的数据,响应头,状态码等。通过这个对象提供的方法,可以获得服务器响应的所有内容。
Spring MVC 在这两个对象的基础上进行了封装,给我们提供更加简单的使用方法。
3.1.2 通过注解获取(@CookieValue):
- 作用:
用于从 HTTP 请求的 Cookie 中获取特定的值并注入到方法参数中。
- 使用位置:
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param6")
public String param6(@CookieValue("gobeyye") String str){
return "gobeyye: " + str;
}
}
不难看到其实使用传统的获取方式也能完成获取 Cookie 信息(指定信息可以通过循环查找一下),注解就是把上面传统公共部分进行封装,使代码看起来更简洁。至于实际开发用哪种,都可以。
3.2 获取 Session:
3.2.1 传统的获取方式:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param7")
public String getSession(HttpSession session){
session.setAttribute("gobeyye","88888");
String str = (String)session.getAttribute("gobeyye");
return str + "存储成功";
}
}
HttpSession 和前面所学的 HttpServletRequest,HttpServletResponse 类似,都是可以直接在方法参数中添加。
3.2.2 通过注解获取(@SessionAttribute):
- 作用:
获取 Session 属性。
- 使用位置:
@Target({ElementType.PARAMETER})
- 生命周期:
@Retention(RetentionPolicy.RUNTIME)
- 使用演示:
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/param8")
public String getSession(@SessionAttribute("gobeyye") String value){
return value;
}
}
结语:
其实写博客不仅仅是为了教大家,同时这也有利于我巩固知识点,和做一个学习的总结,由于作者水平有限,对文章有任何问题还请指出,非常感谢。如果大家有所收获的话,还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。