注解知识回顾
第一:分类
(1)jdk自带的注解(5个):常用的就一个:@Override
(2)元注解(5个):常用的两个:@Target(指定注解使用的位置) @Retention(描述生命周期)
(3)自定义注解:(框架里大部分都是)
第二:元注解
@Target 指定其他注解可以使用的位置(包上、类上、方法上、属性上)
@Retention 指定其他注解的生命周期(源文件中、运行时、class文件中)
@Documented 表示将该注解描述的注解内部的注释部分,也生成到相应的API中
第三:自定义注解
自定义注解需要配合元注解使用(常用@Target&@Retention )
第四:@Target注解(指定其他注解可以使用的位置)
(1)其他注解使用在单个位置(如何指定?)
@Target(ElementType.Type)
(2)其他注解使用在多个位置(如何指定?)底层维护的是一个数组
@Target({ElementType.Type,ElementType.Field})
(3)@Target注解的取值{值被维护在ElementType中}
ElementType.Type
ElementType.Field
ElementType.Method
第五:@Retention注解(指定其他注解的生命周期)
@Retention注解的取值{值被维护在RetentionPolicy工具类中}
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
第六:自定义注解阐述
(1)定义:
@inteface 注解名{}
(2)配合元注解,指定自定义注解使用的位置,以及自定义注解的生命周期
第七:给注解添加功能---属性(也有人称为方法)
定义(1):
@inteface Annotation{
String name(); //没有设置默认值,使用该注解时,该属性必须添加值。
//String name() default "lisi";//给name赋默认值lisi,设置了默认值后,使用该注解不需要手动设置name的属性值。
}
使用(1):
@Annotation(name="zhangsan")
public void sayhello(){
}
定义(2):
@inteface Test{
int value();
//int value() default 10;//给value赋默认值10
}
使用(2):
@Test(value=100)
public void sayhello(){
}
由于value的特殊性,在使用注解时,可以省略“value=”,例如@Test(100)
如果想直接使用@Test不写值100,可以在定义注解时,设置value的默认值为100
@inteface Test{
int value() default 100;//给value赋默认值100
}
问题分析:
@inteface Test{
String name() default "lisi";//给name赋默认值lisi
int value() default 100;//给value赋默认值100
}
(1)可以直接使用这个注解,直接写@Test
(2)保留name的默认值,改value的值("value="可省略)@Test(10)
(3)保留value的默认值,改name的值(“value=”可省略)
@Test(name="张三")
(4)同时改两个值时("value="不能省略)
@Test(name="张三",value=10)
第八:框架(framework)中常用的注解
(1)@SpringBootApplication
描述SpringBoot工程启动类的特定注解
(2)@SpringBootTest
描述SpringBoot工程测试类的特定注解
使用条件:如果需要在测试类中,引入spring容器机制,这是才是用该注解,否则没必要加。
引入spring容器机制:比如说,我们要在测试类中,通过spring容器来注入某个类的实例时,就需要使用该注解。
(3)@AutoWired
自动装配-由Spring框架为我们指定的属性类型注入值.我们常用接口类型的变量来接收spring框架注入的值(多态的思想,为了降低耦合,让程序更容易维护)
具体的注入(DI)过程:
@AutoWired
Student student;
属性的类型 属性名
(1)第一:(Student为一个类)spring框架会基于属性的类型的首字母小写(student)作为key去bean池(单例)中(多例用的时候才创建)去寻找对应的value(这个value就是对象),在注入给这个属性名(注入的其实是一个地址而并非对象);
(2)第二:(Student为接口类型)若该实现类只有一个,则直接注入;
(3)第三:若该接口的实现类有多个,此时会根据属性名student,去查找对应的实现类创建的对象(这个对象存在map中的key为类名首字母小写),找到直接注入,找不到就直接抛异常:NoUniqueBeanDefinitionException
解决办法两种:(一般开发中都不推荐)方法1:修改bean的名字(默认是类名首字母小写);@Component (“指定的名字”),这个指定的名字必须与我们要注入的属性名一摸一样; 方法2:修改属性名(改成某个实现类的类名首字母小写);
常用方法就是指定用哪个实现类!使用( @Qualifier 注解)
@AutoWired(required=false)在项目启动的第一时间,可以不注入值(能注入则注入,不能注入则跳过)。
与@Resource注解装配过程区分,参见@Resource注解(位置:第47个注解)
(4)@Component
不明确这个类属于哪层时可以用该注解,将该类 的实 列交给spring容器创建
(5)@Controller
该注解用于描述控制层,将控制层的实例创建权限 交给spring容器
返回的是view
(6)@Service
该注解用于描述业务层,由spring来创建@Service 描述的类的实例
(7)@Lazy
该注解用于延迟对象的创建,在springboot项目中,对于 单例对象默认在项目启动时创建,这样会耗时耗资源-单例对象是要存 到bean池中的,通常配合[@Scope(singleton)]注解使用,对于 @Scope("prototype")描述的类的对象就是在需要时创建,按需加 载,故@Lazy注解对多利作用域对象不起作用
(8)@Scope
有两个取值@Scope("prototype")、 @Scope("singleton")
(9)@Test
(单元测试的注解)
满足以下条件 (1)访问修饰符不能为private (2)返回值必须为void (3)方法参数必须时无参 (4)测试方法允许抛出异常
扩展----测试的第二种方法(CommandLineRunner)
在启动类(@SpringBootApplicaton)中实现这个接口,重写 run()方法,在run()方法中写我们测试代码;当启动类启动时会自动执行run()方法
(10)@Bean
通常用于配置类中,与@Configuration配合使用
@Bean描述的方法的返回值(返回的是一个对象)交给spring去 管理。此时可以配合@Lazy注解使用
(11)@Mapper
添加在数据层的接口上,通知spring,该接口的实现类有mybatis负责实现,该实现类的对象有mybatis创建,但是交给spring管理
(12)@MapperScan("接口文件的包名")
添加在主启动类上,利用包扫描的方式,为指定包下的接口创建代理类以及代理对象并交给spring管理
优势:不用在每个映射的接口上使用@Mapper注解了
前提:要将所有的映射文件放在同一个包下。
(13)@Repository
添加在数据层接口的实现类上,将这个类交给Spring管理
(14)@Param
当mybatis版本相对较低时,在动态sql中想要使用方法中的参数变量来获取数据,就需要使用该注解对参数变量进行描述
也与jdk的版本有关(往下看~~~~)
原理:mybatis中规定,默认条件下可以进行单值传递 后端用任意的参数接收都可以。
有时候可能进行多值传递,需要将多值封装为map集合进行参数的传递(sql中通过key来取值)
旧版本时如果需要封装为单值,则必须添加@Param注解
新版本时可以自动添加@param,前提条件是多值传递
单值:数组 collection="array" (mapper层传的是数组,此时数组就是一个单值,此时xml中的collection="array")
单值:集合 collection="list" (mapper层传的是list集合,此时数组就是一个单值,此时xml中的collection="list")
多值:利用@param注解封装 collection="key"(mapper层传的是map,此时这个map就是一个单值,此时xml中的collection="key")
(15)@ReponseBody
1.描述的方法的返回值不是view(不是一个页面),
2.比如说可以是一个字符串String---直接返回该字符串
3.当方法的返回值是一个或多个pojo对象(也可以是map)时,springmvc去查看这个方法上是否有该注解,若有,就会pojo对象转成JSON格式的字符串(字符串数组)
(16)@RestController
@Controller+@ReponseBody
一般适用于ajax,不走视图解析器,并且返回json数据
(17)@PathVariable
当我们的方法参数要从url中获取参数时,就需要使用该注解--restful风格中常用!
如果url中的名字与方法参数名不一致,还可以指定
url="menu/menulist"
1.url中的名字与方法参数名一致,可以直接加上@PathVariable,不用指定别名
@RequestMapping("{do}/{dolist}")
public String domain(@PathVariable String dolist){
return dolist;
}
@RequestMapping("{do}/{dolist}")
public String domain(@PathVariable String do){
return do;
}
* * *
2.url中的名字与方法参数名不一致,还可以指定,表明方法参数中的变量时来自url中的哪一个
(一般不用这样的,直接写成一样就可以了(第一种))
@RequestMapping("{do}/{dolist}")
public String domain(@PathVariable("dolist")String name){
return name;
}
@RequestMapping("{do}/{dolist}")
public String domain(@PathVariable("do")String name){
return name;
}
(18)@RequestMapping
请求映射-提供映射路径-可以使用在类上、方法上
(19)@ControllerAdvice
该注解描述类为全局异常处理类
当Spring mvc(web)的控制层出现异常,首先会检查controller中是否有对应的异常处理方法,有则直接执行,若没有,就会检索是否有@ControllerAdvice描述的类,若有,则再去检索类中是否有对应的异常处理方法。。
(20)@ExceptionHandler
该注解描述的方法,为一个异常处理的方法,注解中需要指定能处理的异常类型(RuntimException.class-字节码对象),表示该方法能够处理该类型的异常以及子类异常。
在异常处理方法中,通常需要一个异常参数,用来接收异常对象。
方法的返回值通常是一个对象(json格式-满足响应式布局),通常与@ReponseBody注解结合使用
(21)@Aspect
该注解描述的类为一个切面(aop)
(22)@Around(环绕通知)优先级最高
执行目标方法之前Spring会检测是否有切面(@Aspect描述的类),然后检测是否有通知方法(@Around注解描述的方法),有该方法则执行该方法,在方法中调用通过ProceedingJoinPoint对象jp调用proceed()方法(该方法会执行目标方法)
(23)@Before
当@Around注解描述的方法中,要执行目标方法之前(proceed方法执行之前),执行该注解描述的方法
(24)@After
目标方法执行之后,执行此注解描述的方法(如果目标方法有异常该方法不执行)
(25)@AfterReturnning
@After注解描述的方法执行之后,(这个方法执行了,说明目标方法没有抛出异常)执行该注解描述的方法。
(26)@AfterThrowing
@Around注解描述的方法中的目标方法执行时抛出异常了,就直接执行该注解描述的方法。
(27)@Slf4j(lombok中)
应用在类上,此类中就可以使用log对象
就相当于在这个类中添加了一行如下代码
Logger log=LoggerFactory.getLogger(类名.class);
(28)@PointCut
该注解用来定义切入点方法
@Pointcut("bean(sysUserServiceImpl)")
**public** **void** logPointCut() {}
切入点表示有四种:
bean execution within @annocation
(29)@Order(1)
该注解用于指定切面的优先级,数字越小,优先级越高,默认值是整数的最大值即默认值的优先级是最低的
(30)@Transactional
该注解可以描述类和方法,
当描述类时,表示类中的所有方法在执行之前开启事务,方法执行之后结束事务。
当描述方法时,表示该方法在执行之前开启事务,方法执行之后结束事务。
优先级问题:当类上和方法上都有该注解时,方法上的优先级高于类上的。
该注解中的属性也很重要:
timeout:设置超时时间
isolation:设置隔离级别
rollbackfor:当遇到什么异常以及子类异常时要执行回滚操作。
read-only:指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置read-only为true。对添加,修改,删除业务read-only的值应该为false。
propagation:
Propagation.REQUIRED(如果没有事务创建新事务, 如果当前有事务参与当前事务, Spring 默认的事务传播行为是PROPAGATION_REQUIRED,它适合于绝大多数的情况。)
Propagation.REQUIRES_NEW
如果有当前事务, 挂起当前事务并且开启新事务
(31)@EnableAsync
注解应用到启动类上,表示开启异步,spring容器启动时会创建线程池
spring中线程池的配置:
spring:
task:
execution:
pool:
queue-capacity: 128
core-size: 5
max-size: 128
keep-alive: 60000
thread-name-prefix: db-service-task-
(32)@Async
在需要异步执行的业务方法上,使用@Async方法进行异步声明。
说明:AsyncResult对象可以对异步方法的执行结果进行封装,假如外界需要异步方法结果时,可以通过Future对象的get方法获取结果。
为了简便某些情况下,我们可以将方法的返回值写成void,这样就不要这么复杂的封装(前提时方法的返回值我们不使用)。
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Async
@Override
public Future saveObject(SysLog entity) {
System.out.println("SysLogServiceImpl.save:"+
Thread._currentThread_().getName());
int rows=sysLogDao.insertObject(entity);
//try{Thread._sleep_(5000);}catch(Exception e) {}
return new AsyncResult(rows);
}
(33)@EnableCaching
在项目(SpringBoot项目)的启动类上添加@EnableCaching注解,以启动缓存配置。
在需要进行缓存的业务方法上通过@Cacheable注解对方法进行相关描述.表示方法的
返回值要存储到Cache中,假如在更新操作时需要将cache中的数据移除,可以在更新方法上使用@CacheEvict注解对方法进行描述。
@Cacheable(value = "menuCache")
@Transactional(readOnly = **true**)
**public** List
value属性的值表示要使用的缓存对象,名字自己指定,其中底层为一个map对象,当向cache中添加数据时,key默认为方法实际参数的组合。
(34)@Value
说明:该注解单独使用(不配合@PropertySource注解)时,此时配置文件已经被加载到spring容器中,表示从spring容器(加载的配置文件)中取值。
该注解配合@PropertySource注解使用时,可以从指定的配置文件中取值,value属性指定配置文件的所在路径@PropertySource(value="classpath:/properties/image.properties",encoding="utf-8")
该注解用于描述属性的值,可以用来取出配置文件中的value值(根据key来取值)(properties、yml)、
properties配置文件的优先级高于yml配置文件的优先级
当这两个文件中都用同一个属性时,优先读取properties配置文件中的,然后读取yml配置文件中的,所有最后得到的是yml>中的(key相同值被覆盖)。
@value(“${server.port}”)
private String port;
说明:
因为配置文件中的value值都是字符串类型,所以这里需要用String类型接收。
该注解配合spel表达式取出配置文件中对应key的值。
(35)@PropertySource(value="classpath:/properties/image.properties",encoding="utf-8")
当配置文件已经被加载到spring容器中了,就不要使用该注解指明加载的配置文件了,容器中有直接用@Value取值即可。
说明:该注解用于类上,作用:读取指定位置的配置文件信息,加载该文件到spring容器中
value属性用来指定配置文件的路径
classpath:/ 指定类目录下的路径(resource目录下)
encoding:用来指定配置文件的编码类型
@PropertySource(value="classpath:/properties/image.properties",encoding="utf-8")
public class ReadProperties{
}
(36)@Data(lombok)
该注解用在pojo类上,作用是生成对应的get/set/toString...方法
toString()方法只会重写自己的属性,不会添加父类的属性。
(37)@Setter(lombok)
该注解用在pojo类上,生成set方法
(38)@Getter(lombok)
该注解用在pojo类上,生成get方法
(39)@NoArgsConstructor(lombok)
该注解用在pojo类上,生成无参的构造方法
(40)@NoArgsConstructor(lombok)
该注解用在pojo类上,生成全参的构造方法
(41)@Accessors(chain=true)(lombok提供)
提供链式加载(对于set方法)
User user=new User();
user.setName("张三").setAge(26).setScore(98);
(42)@TableName(“表名”)(mybatisplus提供)
该注解用在pojo类上,用来指定该类的对象,与数据库中的哪张表映射
当pojo类名忽略大小写时,与数据库中要映射的表名一致时,可以不指定表名。如直接写@TableName注解即可。但不能省略这个注解。
(43)@TableId(type=IdType.Auto)(mybatisplus提供)
该注解用于pojo类中的属性上,用来指定表中的主键要映射到pojo类中的哪个属性。
(44)@TableField(value="字段名")(mybatisplus提供)
@TableField(fill = FieldFill.INSERT)指定哪个属性,在新增时有效,一般是创建时间
@TableField(fill = FieldFill.INSERT_UPDATE)指定哪个属性,在新增和修改时有效,一般是创建时间/修改时间
该注解用于pojo类中的属性上,用来指定表中的字段(除主键外的其他字段)映射到pojo类中的哪个属性。
当字段名与属性名一致时,或者,驼峰命名后字段名与属性名一致时,可以省略这个注解@TableField,即pojo中的属性上不写该注解。
(45)@GetMapping("/page/{moduleName}")
该注解用来处理查询请求,其他请求无效。
该注解相当于
@RequestMapping(value="/page/{moduleName}",method=RequestMethod.GET)
restful风格:可以根据请求的方式,来执行特定的业务功能。
TYPE=GET 处理查询业务
TYPE=POST 处理新增业务
TYPE=PUT 处理修改业务
TYPE=DELETE 处理删除业务
result风格总结:
1.可以获取url中的参数配合@PathVariable注解
2.根据请求方式,执行特定的业务功能
(46)@RestControllerAdvice
@RestControllerAdvide=@ResponseBody+@ControllerAdvide
说明:
该注解应用于类上,表示为通知方法。类中的方法的返回值都不是view,返回的是JSON格式的数据。
该注解描述的类为全局异常处理类,处理Controller层出现的异常。
(47)@Resource
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序
- 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
- 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
- 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
- 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
(48)@ComponentScan(basePackages={"包的路径"})
扫描指定路径下的类,看是否有类上@Component、@Controller、@Service、@Mapper等,若有则指明该类的实例由Spring容器创建。
(49)@RequestBody
1、@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。
2、通过@requestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分别绑定到对应的字符串上。
@RequestBody和@RequestParam区别
@RequestParam
注解@RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中。
RequestParam可以接受简单类型的属性,也可以接受对象类型。
@RequestParam有三个配置参数:
required 表示是否必须,默认为 true,必须。
defaultValue 可设置请求参数的默认值。
value 为接收url的参数名(相当于key值)。
@RequestParam
用来处理Content-Type为application/x-www-form-urlencoded编码的内容,Content-Type默认为该属性,也可以接收application/json。@RequestParam也可用于其它类型的请求,例如:POST、DELETE等请求.所以在postman中,要选择body的类型为 x-www-form-urlencoded,这样在headers中就自动变为了 Content-Type : application/x-www-form-urlencoded 编码格式。@RequestBody
注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。就application/json类型的数据而言,使用注解@RequestBody可以将body里面所有的json数据传到后端,后端再进行解析。GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。
POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用
HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。由于@RequestBody可用来处理 Content-Type 为 application/json 编码的内容,所以在postman中,选择body的类型为rowJSON(application/json),这样在 Headers 中也会自动变为 Content-Type : application/json 编码格式。
(50)@JsonFormat
在你需要查询出来的时间的数据库字段对应的实体类的属性上添加@JsonFormat
可以很好的解决:后台到前台时间格式保持一致的问题
(51)@DateTimeFormat
在你需要查询出来的时间的数据库字段对应的实体类的属性上添加@DataTimeFormat
可以很好的解决:前台到后台时间格式保持一致的问题
@DateTimeFormat(pattern ="yyyy-MM-dd")
@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date symstarttime;