Annotation介绍
元注解(基础)
@Target
- 用来声明被修饰的注解可以用在什么位置。可以在**@Target的属性中设置ElementType**类型的数组来指定可以使用的位置。如果不用此元注解修饰,默认注解可以用在任意位置。(为常用注解)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//Type表示->注解作用于类
//FIELD表示->注解作用于属性
//METHOD表示->注解作用于方法
@Retention
- 生命周期,用来声明被修饰的注解会被保留到什么阶段。(为常用注解)
名称 | 解释 | 备注 |
---|---|---|
RetentionPolicy.SOURCE | 此注解将会被保留到源码阶段,即.java中,在编译过程中被删除。 | 这种类型的注解通常是给编译器看的。 |
RetentionPolicy.CLASS | 此注解将会被保留在源码阶段和编译阶段,即.java和.class中,在类加载的过程中被删除。 | 这种类型的注解通常是给类加载器看的。 |
RetentionPolicy.RUNTIME | 此注解将会被保留在源码阶段 、编译阶段 和 运行段。即.java .class和内存中的字节码中都会存在 | 这种类型的注解通常用来在运行阶段进行反射,控制程序运行过程。 |
补充:只有RUNTIME级别的注解才可以通过反射技术进行反射。
@Documented
- 用来声明被修饰注解是否要被文档提取工具提取到文档中。默认不提取。
@Inherited
- 被修饰的注解是否具有继承性,默认没有继承性。
SSM框架常用注解(Spring/SpringMVC/Mybatis)
Application启动类常用注解
@SpringBootApplication
- 该注解放置在Springboot启动类上
- 作用:表明该类是开启Springboot容器的入口,它是一个复合注解,里面包含了包扫描,自动注入,配置注入的功能。
源码如下(片段):
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
@ConfigurationPropertiesScan
@EnableAutoConfiguration
- 该注解标注在类上
- 它表示开启自动配置功能。
源码如下(片段):
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
@AutoConfigurationPackage
- 该注解标注在类上
- 作用:表示自动注入包,将@SpringBootApplication修饰的类的同包,子孙包下的所有组件都扫描到Spring容器中。
源码如下(片段):
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
- @Import({Registrar.class})表明给容器导入一个组件,这个组件的内容就由Registrar.class传入的对象决定。
@ComponentScan
- 该注解标注在类上
- 作用:用来将指定包(如果未指定就是将当前类所在包及其子孙包)加入SpringIOC的包扫描,本质上等于:
<context:component-scan>配置
源码如下(片段):
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {}
@MapperScan
-
该注解标注在类上
-
作用:在启动类中使用@MapperScan(“mapper接口所在包全名”)即可,不用一个一个的在Mapper接口中加@Mapper注解。@Mapper注解是识别他为mybatis的mapper接口,会自动的把 加@Mapper 注解的接口生成动态代理类。
源码如下(片段):
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {}
@SpringBootTest
- 该注解标注在类上
- 作用:表示此类为Springboot的单元测试类
源码如下(片段):
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith({SpringExtension.class})
public @interface SpringBootTest {}
Spring配置类常用注解
@SpringBootConfiguration
- 该注解标注在类上
- 作用:它表示的是该类会作为Springboot的一个配置类,进入该注解,发现里面包含@Configuration注解,进入@Configuration注解,我们发现他是被@Component所修饰的,所以该配置类也是一个组件。
源码如下(片段):
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration //该类为配置类
public @interface SpringBootConfiguration {}
@Configuration
- 该注解标注在类上
- 作用:在Spring里表示该类为配置类。
源码如下(片段):
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component //该类为组件类
public @interface Configuration {}
@Component
- 该注解标注在类上
- 作用:在Spring里表示该类为组件类。
源码如下(片段):
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {}
POJO层
@DateTimeFormat
- 该注解可标注在注解/方法/属性/参数上
- 作用:当使用
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
注解描述此属性时,客户端传值时会调用set方法去给对象属性赋值,客户端需要按此格式为属性传入值,否则客户端报400异常! - 默认格式:
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
public @interface DateTimeFormat {}
@JsonFormat
-
该注解可标注在注解/类/方法/属性/参数上
-
作用: 当使用
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
注解描述属性时,表示调用此属性的get方法取值并转换为字符串时按照pettern指定的格式进行转换。 -
默认值为:
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
若不按照对应格式传值,客户端会报400异常! -
注意点:被转换的时间因时区问题,会少8小时,若需解决此问题,还需在注解参数中添加约束timezone=“GMT+8”。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createdTime;
源码如下(片段):
@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonFormat
{}
@RestControllerAdvice
- 该注解可标注在类上
- 作用:描述此类为全局异常处理类,拦截异常并统一处理。等价于
@ControllerAdvice
+@ResponseBody
注解。 - 作为特化@Component,允许通过类路径扫描自动检测实现类。它通常用于定义@ExceptionHandler,@InitBinder和 @ModelAttribute 适用于所有@RequestMapping方法的方法。
- 默认行为(即:如果没有任何选择器使用),带@ControllerAdvice注释的类将协助所有已知的控制器。
案例:
package com.cy.pj.sys.web.exception;
import com.cy.pj.sys.web.pojo.JsonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(RuntimeException.class)
public JsonResult doHandleRunTimeException(RuntimeException e){
e.printStackTrace();
log.error("exception msg is {}",e.getMessage());
return new JsonResult(e);
}
@ExceptionHandler(IllegalArgumentException.class)
public JsonResult doHandleIllegalArgumentException(IllegalArgumentException e){
e.printStackTrace();
log.error("exception msg is {}",e.getMessage());
return new JsonResult(e);
}
}
源码如下(片段):
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {}
@ExceptionHandler
-
该注解可标注在方法上
-
作用:需要配合
@RestControllerAdvice
或者@ControllerAdvice
注解才能使用,当被@RestControllerAdvice
注解拦截到某个异常,会通过@ExceptionHandler
注解,跳转到该异常的处理方法去进行处理,处理完成后会返回异常信息并封装返回结果。
源码如下(片段):
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}
全局异常案例
Controller控制层常用注解
@Controller
- 该注解标注在类上
- 作用:表示此类为SpringMVC的Controller对象,定义了此类为控制器类,分发处理器会扫描使用该注解类的方法,并检测该方法是否使用了@RequestMapping注解。
- 被@Controller注解标注的类,类里的方法return时会被视图处理器识别成静态文件的路径。默认为templates文件夹下。如
return "test/hello"
表示的是默认路径下的test文件夹中的名叫hello的文件,带上后缀名.html或btl等也可以识别,也可以在.yml文件中配置页面路径。
源码如下(片段):
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component //该类为组件类
public @interface Controller {}
@RestController
- 该注解标注在类上
- 作用:类中方法return返回的值将被转换成json,字符串除外,直接写入HTTP相应体返回到页面中。
- 等价于@Controller+@ResponseBody(两者效果一样)
源码如下(片段):
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {}
@ResponseBody
- 该类标注在方法/类上
- 作用:当标注方法时表示该方法的返回值会被解析成json(字符串会不会被转换),直接写入HTTP Response Body中,视图处理器将不会将return的参数识别成路径。当它标注类时,类中所有方法的返回值都将直接返回值到页面,相当于给所有的类都加上@ResponseBody注解。
- 底层的DispatcherServlet会调用Jackson API将方法的返回值转换为Json格式字符串。
- 底层转换时会调用返回值对象的get方法,以get方法的方法名(去掉get单词,首字母小写)为key,get方法的返回值为value,来构建Json字符串。
- 可尝试删掉POJO层对象属性的get方法进测试,若缺少某个get方法,仍可以正常返回其他属性的值,若缺少全部属性的get方法,只剩set方法,客户端会直接报500错误!!
源码如下(片段):
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {}
@ResquestBody
- 该类标注在参数上
- 作用:告诉服务端接收json数据
- 若参数被@ResquestBody描述,客户端提交数据的要求:
- 请求方式:post
- 请求Content-Type设计:application/json
- 请求数据格式{“key1”:“value1”,“key2”:“value2”,…}
- 假如服务端的方法参数使用了@ResquestBody修饰
源码如下(片段):
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
boolean required() default true;
}
@PathVariable
- 该类标注在参数上
- 作用:用来接收rest风格的url的参数
@GetMapping("/notice/doFindById/{id}")
@ResponseBody
public JsonResult doFindById(@PathVariable Long id){
return new JsonResult();
}
源码如下(片段):
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {}
@RequestParam
- 该类标注在属性上
- 作用:对传统请求参数进行约束。方法参数为Map时,必须用此注解进行描述。
源码如下(片段):
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {}
@Autowired
-
该注解可用在参数/属性/方法/注解/构造函数上
-
作用:自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入被他管理的 bean 类型。当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就报错。
-
通俗来讲:告诉Spring框架,要基于反射机制给属性赋值(依赖注入),假如只有一个则直接注入,有多个相同类型的对象时,还会比较属性名(检测属性名是否与bean名字相同,有相同的则直接注入(没有相同的直接抛出异常)。
源码如下(片段):
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {}
案例:
@Autowired
private UserMapper userMapper;
@RequestMapping
- 该注解作用于类和方法上
- 作用:在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置
XML配置方法如下:
<servlet>
<servlet-name>servletName</servlet-name>
<servlet-class>ServletClass</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletName</servlet-name>
<url-pattern>url</url-pattern>
</servlet-mapping>
源码如下(片段):
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {}
@CrossOrigin
- 该注解作用于类和方法上
- 作用CORS(俗称跨域资源共享) 在响应头中标识哪些网址可以访问服务器,CORS的配置是服务器端的配置和浏览器没关系。(解决跨域问题,详见:https://blog.csdn.net/qq_16804847/article/details/115063493?spm=1001.2014.3001.5501)
源码如下(片段):
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {}
Mybatis忽略NULL值解决方法
// 实体类加此注解
@TableField(strategy=FieldStrategy.IGNORED)