🫒开发中的常用注解-随手记
JDK注解:
@PostConstruct和@PreDestroy:程序启动与卸载时加载
参考链接:https://blog.csdn.net/sunayn/article/details/92840439、https://www.cnblogs.com/codingmengmeng/p/10760492.html
@PostConstruct说明
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的init()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
也可以理解为在spring容器启动的时候执行,可作为一些数据的常规化加载,比如数据字典之类的。
@PostConstruct注解是JSR-250规范定义的,在对象实例化后,初始化之前执行的方法上使用该注解。
它告诉Spring容器在对象创建后调用带有该注解的方法。因此,@PostConstruct注解的方法在@Autowired注解之后执行。
@PreDestroy说明
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。
这两个注解被用来修饰一个非静态的void()方法。使用方法如下:
@PostConstruct
public void someMethod(){}
或者
public @PostConstruct void someMethod(){}
示例:
@PostConstruct
public void initMethod() {
System.out.println("程序加载时候,我被执行了~~~");
}
@PreDestroy
public void shutdownMethod() {
System.out.println("程序停止时候,我被执行了~~~");
}

Servlet常用注解:
@WebServlet:注册servlet
编写好Servlet之后,接下来需要要告诉Web容器有关于这个Servlet的一些信息。
在Servlet 3.0中,可以使用标注(Annotation)来告知容器哪些Servlet会提供服务以及额外信息。
也就是说:web.xml中对Servlet配置,同样可以在 @WebServlet 注解中配置.
需要注意的是:
如果是SpringBoot项目,需要在主启动类上面添加@ServletComponentScan注解

下面使用xml与注解进行一个比对:

MyBatis常用注解:
@Param :传递参数
- @Param是MyBatis所提供的(org.apache.ibatis.annotations.Param),
- 作为Dao层的注解,作用是用于传递参数,从而可以与SQL中的的字段名相对应,一般在2=<参数数<=5时使用最佳。
- @Param是地处Dao层,是为了传递多个参数,解决的是可读性和直观性;
- 在方法只接受一个参数的情况下,可以不使用@Param。
- 在方法接受多个参数的情况下,建议一定要使用@Param注解给参数命名。
- 如果参数是 JavaBean , 则不能使用@Param。
- 不使用@Param注解时,参数只能有一个,并且是Javabean。
- 基本类型 的参数或者String类型都需要加上
- 引用类型不需要加
- 我们在sql 中引用的就是我们这里的@Param("")中设定的属性名

@Mapper:标记持久层
@Mapper与@Repository的相同点
两个注解都可在dao/mapper层使用(用来标记持久层),生成相应代理对象bean注入到spring容器中。
@Mapper与@Repository的不同点
@Mapper是mybatis的注解,可以单独使用,也允许存在在多个mapper文件,它不需要在Spring中配置扫描地址,通过xml里面的namespace里面的接口地址,生成Bean后注入到Service层中。
@Repository是spring提供的注解,能够将该类注册成Bean。被依赖注入,但是使用该注解后,在启动类上要加@MapperScan来表名Mapper类的位置,否则扫描不到。但在idea中,使用@Repository可以消除在业务层中注入mapper对象时的错误。
@MapperScan:扫描持久层接口

@MapKey("id"):标记Map的key为指定属性值
这样相对于:List<Map<String,Object>>的遍历查找数据,效率要快很多,直接通过map.get("id")即可查询数据
只需要在dao/mapper层接口方法上面加上该注解即可:
/**
* 查询所有的Car,返回一个Map集合
* Map集合的key是每条记录的主键值
* Map集合的value是每条记录
* @return 对象集合
*/
@MapKey("id")
Map<Long, Map<String, Object>> selectAllByMap();
测试:
/**
* {
* 1={car_num=100, id=1, guide_price=41.00, produce_time=2022-09-01, brand=宝马520Li, car_type=燃油车},
* 2={car_num=101, id=2, guide_price=54.00, produce_time=2022-08-01, brand=奔驰E300L, car_type=电车},
* 4={car_num=103, id=4, guide_price=25.80, produce_time=2022-01-01, brand=丰田, car_type=燃油车},
* 5={car_num=103, id=5, guide_price=25.80, produce_time=2022-01-01, brand=丰田, car_type=燃油车},
* 7={car_num=104, id=7, guide_price=10.00, produce_time=2022-11-17, brand=比亚迪汉, car_type=电车}
* }
*/
@Test
public void testSelectAllByMap() {
SqlSession sqlSession = MybatisUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Map<Long, Map<String, Object>> resultMap = mapper.selectAllByMap();
System.out.println(resultMap);
System.out.println("获取id为5的记录");
Map<String, Object> map = resultMap.get(5L);
System.out.println(map);
}
Mybatis-Plus常用注解:
@TableName
注解在类上,指定类和数据库表的映射关系。实体类的类名(转成小写后)和数据库表名相同时,可以不指定该注解。
@TableId
注解在实体类的某一字段上,表示这个字段对应数据库表的主键。
在插入数据的时候如果不指定id的数据,mp会自动进行填充数据(雪花算法)
@TableField
注解在某一字段上,指定Java实体类的字段和数据库表的列的映射关系。这个注解有如下几个应用场景。
数据库表跟实体类属性不对应:比如数据库中是"name",实体类中是private String username,就需要通过指定数据库中的字段名称

排除非表字段:若Java实体类中某个字段,不对应表中的任何列,它只是用于保存一些额外的,或组装后的数据,则可以设置exist属性为false,这样在对实体对象进行插入时,会忽略这个字段。
排除非表字段也可以通过其他方式完成,如使用static或transient关键字
不查询指定字段属性:在我们查询数据的时候有时候并不想查询显示某一列的数据,就可以设置select属性为false @TableField(select = false)
字段验证策略通过insertStrategy,updateStrategy,whereStrategy属性进行配置,可以控制在实体对象进行插入,更新,或作为WHERE条件时,对象中的字段要如何组装到SQL语句中。
字段填充策略:在表中做数据库的更新和插入字段的时候填充数据,只需要实体类中指定file属性
步骤1、在实体类添加注解
步骤2、自定义实现类 MyMetaObjectHandler:https://mp.baomidou.com/guide/auto-fill-metainfo.html

@Version乐观锁注解
@EnumValue注解在枚举字段上
@TableLogic逻辑删除
作用在实体类的属性上面,表示逻辑删除,指的是不会真正的从数据库中删除记录,而是将deleted(逻辑删除)字段更新为1
*:逻辑删除实质上是执行update语句

KeySequence序列主键策略(oracle)
InterceptorIgnore插件过滤规则
Lombok常用注解:
1、要在idea中添加lombok插件
2、配置lombok的Maven依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency>
@Data :设置set/get等方法
@AllArgsConstructor:有参构造
@NoArgsConstructor:无参构造
@Builder:链式调用
TestUser testUser = TestUser.builder()
.name("李四")
.age(24L)
.addredd("北京丰台")
.build();
@FieldNameConstants:获取字段名常量
/**
* @ClassName User
* @Author zhangzhixi
* @Description
* @Date 2022-11-08 16:36
* @Version 1.0
*/
@Data
@FieldNameConstants
public class User implements Serializable {
private String name;
private Integer sex;
public static void main(String[] args) {
// sex
System.out.println(Fields.sex);
}
}
Spring常用注解:
xml跟注解在开发中的区别:
xm|与注解: 。xml更加万能,适用于任何场合!维护简单方便 。注解不是自己类使用不了,维护相对复杂! xml与注解最佳实践: 。xml用来管理bean; 。注解常用于负责完成属性的注入; 。我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
首先在xml文件中导入约束(以及注解的支持):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--注解的支持--> <context:annotation-config/>
<!--扫描包,说明在这个包下的注解会被识别-->
<context:component-scan base-package="com.zhixi"/>
</beans>
@Component:注册bean
放在类上面,表示一个组件,说明这个类被spring管理了、 等价于:<bean id="user" class="com.zhixi.pojo.类名"/>
属性:value 就是对象的名称,也就是bean的id值value的值是唯一的
@Component(value = "user")
如果不指定value属性就表示类名首字母小写:User-->user
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层! 。dao (持久层)[@Repository] 放在dao的实现类上面,表示创建dao对象, dao对象是能访问数据库的。 。service (业务层)[@Service] 放在service的实现类上面,创建service对象, service对象是做业务处理,比如处理事务等功能的、 。controller (控制器层)[@Controller] 控制器对象,能够接受用户提交的参数,显示请求的处理结果。 这四个注解功能都是一 样的,都是代表将某个类注册到Spring中, 装配Bean
组件扫描器的声明需要在spring框架的核心配置文件来注册
<context:component-scan base-package="指定Spring容器需要扫描的类所在包"/>
@PathVariable
映射 URL 绑定的占位符 带占位符的URL
@Value:给基本类型属性赋值
1.作用:为对象中基本类型属性进行赋值
类似于XML标签中<property name="基本属性名" value="赋值内容"/>
2.使用:
@Value可以修饰在属性上方,此时这个属性不需要声明set方法
@Value可以修饰在set方法上方
3.注意:
@Value出现类必须使用@Componet进行修饰
给基本类型属性赋值,也可以放在属性的setter方法上,是一样的
@Value("张三")
/*等价于:<property name = "name" value = "张三"/>*/
private String name = "张志喜";
扩展:使用${xxx}给属性赋值:
1、xxx.properties
name=张三
age=23
2、xml中加载属性配置文件
<context:property-placeholder location="classpath:students.properties" file-encoding="gb2312"/>
3、使用@Value注解
@Value("${name}")
private String name;
@Value("${age}")
private int age;
SpringBoot中使用@Value给POJO属性赋值
给属性赋值也可以通过@ConfigurationProperties方式,下面使用@Value方式:
1、配置文件中添加自定义属性:application.properties
mycar.brand=BYD mycar.prices=100000
2、POJO实体类,导入属性
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component// 只有添加为组件才能够使用配置绑定功能
public class Car {
/**
* 汽车品牌
*/
@Value("${mycar.brand}")
private String brand;
/**
* 汽车价格
*/
@Value("${mycar.prices}")
private Integer prices;
}
3、使用导入的属性
@RestController
public class MyController {
@Autowired
Car car;
@RequestMapping("/car")
public Car myCar() {
return car;
}
}

@Value给静态变量赋值
参见:https://zhuanlan.zhihu.com/p/503653536
@AutoWired :给引用类型属性赋值(默认是byType注入方式)
1、spring 框架提供的注解,实现引用类型的赋值。
2、spring中通过注解给引用类型赋值,使用的是自动注入原理, 支持byName,byType
3、放在属性上,自动装配名字、类型。也可以加到setter方法上[常用]
@Autowired
private School school;
@Primary:指定按照byTepe注入的顺序
因为按类型自动注入可能会导致多个候选者,所以经常需要对选择过程进行更多的控制。
实现这一目标的方法之一是使用Spring的 @Primary 注解。@Primary 表示,当多个Bean是自动注入到一个单值(single value)依赖的候选者时,应该优先考虑一个特定的Bean。
如果在候选者中正好有一个主要(primary)Bean存在,它就会成为自动注入的值。
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
@Qualifier:配合@AutoWired使用(使用的是byName方式的注入)
1、如果@Autowired自动装配的环境比较复杂【比如多个bean对象】,自动装配无法通过一个注解[@Autowired] 完成、
2、我们可以使用@Qualifier(value="xx")配合@Autowired使用,指定一个唯一 的bean对象注入!
@Autowired // 表示自动注入
@Qualifier("mySchool") //表示找名字
private School school;
@Resouece:给引用类型属性赋值
1、来自Jdk的注解,resource默认通过byname的方式实现
2、如果找不到名字,则通过byType实现! 如果两个都找不到的情况下,就报错! [常用]
3、也可以指定bean的id-->byName方式:@Resource(name = "dog2")
@ComponentScan :扫描包
-该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <context:component-scan>
-或者是@ComponentScan("com.zhixi.pojo") 扫描指定的包、等同于:<context:component-scan base-package="com.zhixi.pojo"/>
@Scope:指定作用域
表示类的作用域,默认是 prototype【原型】,也可以指定作用域:
@Scope("prototype")
/*等价于:<bean scope="prototype"/>*/
Aop
切面的执行时间,这个执行时间在规范中叫做Advice(通知,增强),在aspectj框架中使用注解表示的。也可以使用xml配置文件中的标签
Aop对指定注解做切面
//自定义注解
@Target(value = ElementType.METHOD)//限制运行在方法上
@Retention(value = RetentionPolicy.RUNTIME)//运行时有效
public @interface GmallCache {
String cacheName() default "cache";
}
环绕通知-切入点表达式
@Slf4j
@Aspect
@Component
public class ApiTimeLogAspect {
/**
*
* // 第一种:直接写切点表达式: @Around(value = "@annotation(com.zhixi.annotation.GmallCache))")
* // 第二种:写切点表达式的引用: @Around(value = "@annotation(gmallCache)"),需要在方法参数加上加入想要增强的那个注解
* @param proceedingJoinPoint 执行目标方法的参数
* @return 返回目标方法的执行结果
* @throws Throwable proceedingJoinPoint.proceed()方法抛出的异常
*/
@Around(value = "@annotation(gmallCache)")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint,GmallCache gmallCache) throws Throwable {
// 记录接口执行前的时间戳
long startTime = System.currentTimeMillis();
// 实际执行目标方法,类似动态代理的invoke()执行目标方法
Object result = proceedingJoinPoint.proceed();
// 计算接口耗时
log.info("------------ 耗时: {} ms ------------", System.currentTimeMillis() - startTime);
// 只做增强不做改变,还是要把接口原本的结果返回
return result;
}
}
@EnableAspectJAutoProxy:启用AspectJ自动代理支持
AspectJ是一种基于Java的面向切面编程(AOP)框架,允许开发人员在程序中定义“切面”,以实现跨越多个方法的公共功能。
@EnableAspectJAutoProxy注解告诉Spring框架启用AspectJ自动代理,从而允许应用程序使用AspectJ切面。
这意味着可以使用AspectJ的@Aspect注解定义切面,并使用@Pointcut注解定义切入点,以及使用@Before,@After等注解定义增强处理。
@Aspect:标注切面
切入点表达式
execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])
访问控制权限修饰符:
- 可选项。
- 没写,就是4个权限都包括。
- 写public就表示只包括公开的方法。
返回值类型:
- 必填项。
- * 表示返回值类型任意。
全限定类名:
- 可选项。
- 两个点“..”代表当前包以及子包下的所有类。
- 省略时表示所有的类。
方法名:
- 必填项。
- *表示所有方法。
- set*表示所有的set方法。
形式参数列表:
- 必填项
- () 表示没有参数的方法
- (..) 参数类型和个数随意的方法
- (*) 只有一个参数的方法
- (*, String) 第一个参数类型随意,第二个参数是String的。
异常:
- 可选项。
- 省略时表示任意异常类型。
匹配service包下所有的类中以delete开始的所有方法 execution(public * com.powernode.mall.service.*.delete*(..)) 匹配MyService类下所有以delete开始的所有方法 execution(* com.example.service.MyService.delete*(..)) 匹配mall包及其子包下所有的类的所有的方法 execution(* com.powernode.mall..*(..)) 所有所有类的所有方法 execution(* *(..)) 匹配修饰符为public的所有方法: execution(public * *.*(..)) 匹配com.example包及其子包下的所有方法: execution(* com.example..*.*(..)) 匹配com.example.service包下的所有类的所有方法(不包含子包): execution(* com.example.service.*.*(..)) 匹配com.example.service.MyService类下的所有方法: execution(* com.example.service.MyService.*(..)) 匹配com.example.service.MyService类下的myMethod方法: execution(* com.example.service.MyService.myMethod(..)) 匹配返回类型为String的所有方法: execution(String *.*(..))
作用在类上面,标注这个类是一个切面
@Before():在切面前执行什么方法
@After():在切面后执行什么方法
@AfterReturning
@Around
@AfterThrowing
具体查看博客:AOP编程
SpringMVC常用注解:
@Controller:控制器
作用在类上。用于声明Spring发类的实例是一个控制器
@RequestMapper:请求映射
相当于servlet中xml配置的<servlet-mapper>
@RequestMapping注解用于映射urI到控制器类或个特定的处 理程序方法。可用于类或方法上。
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
1 // 请求映射,通过/some来访问到:WEB-INF/jsp/hello.jsp 2 @RequestMapping("/some") 3 public String getName(Model model){ 4 // 封装数据 5 model.addAttribute("msg","hello annocation SpringMVC"); 6 // 返回视图的名字,会被视图解析器处理 7 return "hello"; 8 }
参数produces解决请求乱码问题: produces = "text/plain;charset=utf- 8"
默认使用“text/plain;charset= ISO- 8859- 1f作为contentType,导致中文有乱码, 解决方案:给Reques tMapping增加一个属性produces, 使用这个属性指定新的content Type
@PathVariable:路径变量
作用在形参上面,用于表示这个参数是一个RestFull风格的URL
参考博客 :RestFull风格
@RequestBody:主要用来接收前端传递给后端的json字符串中的数据(json-->Java对象)
原文链接:https://blog.csdn.net/justry_deng/article/details/80972817
最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。
在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
@RequestParam:将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)
语法:@RequestParam(value=”参数名”)
举例:
<form action="/encoding" method="get"> <div><input type="text" name="username"></div> <div><input type="submit" value="提交"></div> </form>
@Controller public class EncodingDemo { @RequestMapping(value = "/encoding", method = RequestMethod.GET) public String encoding(@RequestParam("username") String name, Model model) { System.out.println(name); model.addAttribute("msg", name); return "encoding"; } }
如果在controller中获取前台页面请求参数的name,跟形参的名字不一致就会出现404、因为它找的是username,而形参中是String name
所以要通过@RequestParam在Controller中进行指定。
@RestController: 不会走视图解析器
@Controller :会走视图解析器
@RestController:不会走视图解析器,会返回一个字符串
@Controller跟@RestController的区别:https://www.cnblogs.com/zhangzhixi/p/14316924.html
JSON常用注解:
使用前先导入Maven依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.2</version> </dependency>
@RestController: 作用在类上,表示程序不会走视图解析器
@Controller :会走视图解析器
@RestController:不会走视图解析器,会返回一个字符串
@ResponseBody
标注在方法上面表示不会走视图解析器,会直接返回一个字符串到页面
@RestController 注解相当于 @ResponseBody + @Controller 结合在一起的作用
@Controller
public class JsonDemo {
/**
* @author zhangzhixi
*/
@RequestMapping(value = "/json")
@ResponseBody // 表示不会走视图解析器,会直接返回一个字符串到页面
public String json1() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// 创建一个对象
User user = new User("张志喜", 21, "男");
// 将值写为字符串[将对象转为JSON格式字符串]
String str = mapper.writeValueAsString(user);
return str;
}
}
参考:https://www.cnblogs.com/shuaifing/p/8119664.html
SpringBoot常用注解:
@JsonAlias:将Java对象序列化成JSON时使用的属性名称
与@JsonProperty相比,@JsonAlias的一个优点是它可以提供多个属性名称别名,这使得你可以在反序列化JSON时使用多个可能的属性名称。
然而,@JsonProperty更常用,因为它只需要指定单个属性名称,并且可以在序列化和反序列化过程中使用相同的属性名称。
@JsonProperty:将Java对象序列化成JSON时使用的属性名称
@JsonProperty是Jackson库的注解,它可以用于Java类的属性,用于指定将Java对象序列化成JSON时使用的属性名称。这对于将Java对象转换为JSON字符串很有用,因为Java对象的属性名称可能与JSON属性名称不同。
例如前端表单的属性是:user_name、user_pwd,这时候前端发来JSON数据,后端接收json数据就需要使用到@RequestBody注解。
但是后端属性通常是驼峰命名方式,例如:userName、userPwd,这时候就需要通过此注解来进行指定了。以下是UserDTO(数据传输对象)
UserDto:
@Data
public class UserDTO {
@JsonProperty("user_name")
private String userName;
@JsonProperty("user_pwd")
private String userPwd;
}
Controller:
@RequestMapping(value = "/login",method = RequestMethod.POST)
public R userLogin(@RequestBody UserDTO user) {
Map<String, Object> map = new HashMap<>(16);
// TODO 此处模拟从数据库中查询数据
if ("zhangsan".equals(user.getUserName()) && "123".equals(user.getUserPwd())) {
// DTO转POJO
User userPo = new User();
BeanUtils.copyProperties(user, userPo);
map.put("date", userPo);
map.put("message", "登录成功");
map.put("code", HttpStatus.SC_OK);
} else {
map.put("error", "登录失败,请检查用户名或密码");
map.put("code", HttpStatus.SC_INTERNAL_SERVER_ERROR);
}
return R.ok(map);
}

JSON格式化:
/** * 创建时间 */ @TableField(value = "create_time")// 数据库中字段名称 @JsonDeserialize(using = LocalDateTimeDeserializer.class)// 反序列化 @JsonSerialize(using = LocalDateTimeSerializer.class)// 序列化 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")// 对入参进行格式化(比如前端发送数据给后端) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")// 对出参进行格式化 private LocalDateTime createTime;
@JsonFormat:用于Json格式的入参
通常应用于LocalDateFormat的格式化,该注解可以作用于:注解、字段、方法、参数、接口上
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat:用户JSON格式的出参
加入到实体类属性上面,通常应用于LocalDateFormat的格式化,该注解可以作用于:注解、字段、方法、参数上
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ServletComponentScan
在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。
配置文件使用的:参考官方文档
@Configuration:说明这是一个配置文件/配置类
/**
* @author zhangzhixi
* @version 1.0
* @date 2021-11-23 23:14
* 标注了这是一个配置类,相当于一个Spring的配置文件
*/
@Configuration
public class MyConfig {
/**
* @Bean:注解表示这是一个在spring配置文件中注册的组件:
* 默认方法名是bean的名称
* 返回值类型是bean的类型
* 返回值是给bean进行赋值
* 可以通过@Bean("beanName")进行指定bean的名字
*/
@Bean("tom")
public Tom getTom() {
return new Tom("tomcat", 2);
}
}
@Configuration的参数:proxyBeanMethods
@Configuration( proxyBeanMethods = false)
proxyBeanMethods属性默认值是true,也就是说该配置类会被代理(CGLIB),在同一个配置文件中调用其它被@Bean注解标注的方法获取对象时会直接从IOC容器之中获取;
注解的意思是proxyBeanMethods配置类是用来指定@Bean注解标注的方法是否使用代理,默认是true使用代理,直接从IOC容器之中取得对象;
如果设置为false,也就是不使用注解,每次调用@Bean标注的方法获取到的对象和IOC容器中的都不一样,是一个新的对象,所以我们可以将此属性设置为false来提高性能;
简单来说就是如果:
配置的组件之间有依赖关系,就配置成true(会加载变慢)
没有需要进行依赖的的组件,就可以配置成false(使用的时候再创建,提高新能~)
@ImportResource:用于导入Spring的配置文件,让配置文件里面的内容生效
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,不能自动识别;
想让Spring的配置文件生效,加载进来; @ImportResource 标注在一个配置类上。
如果将 @importResources 注释掉,那么helloKitty这个组件就不会注册到IOC容器中!

@PropertySource
// 绑定.properties配置文件
@PropertySource(value = "classpath:application.properties")
配合 @Value 注解给属性赋值


@ConfigurationProperties
配置@Component注解使用,表示这是一个组件,才能够使用SpringBoot的功能。
// 作用在类上,常用于yaml配置文件,给属性赋值
@ConfigurationProperties(prefix = "yaml配置文件属性名")

@Conditional:按需加载组件
可以参考博客:Spring Boot @Condition 注解,组合条件你知道吗
//作用在类上,spring的底层注解,根据不同条件判断配置或类是否生效!
@ConditionalOnWebApplication(type = ConditionalOnWebApplication. Type . SERVLET)
@Enablexxx:开启某个功能
@EnableWebSecurity :开启WebSecurity模式
@EnableConfigurationProperties :自动配置属性--> @EnableConfigurationProperties(HttpProperties. class)
@EnableSwagger2 :开启swagger,参考博客:https://www.cnblogs.com/zhangzhixi/p/14348822.html
@EnableAsync :在程序的主入口类中添加,表示开启异步任务
@ControllerAdvice:表示这是个增强类(底层是@Component,一个组件)
第一种用法:配合@ExceptionHandler做全局异常处理
@ExceptionHandler ({ArithmeticException.class,NullPointerException.class}):作用在方法上面,处理什么异常信息
看下处理异常的设置:
/**
* @ClassName GlobalExceptionHandling
* @Author zhangzhixi
* @Description 全局异常处理
* @Date 2022-6-25 17:07
* @Version 1.0
*/
@ControllerAdvice(value = {"com.zhixi.controller"}) // 指定哪些包下的请求被全局异常处理
public class GlobalExceptionHandling {
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handleException(Exception e) {
/*发生异常后的视图返回地址*/
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("errorMessage", "发生" + e.getMessage() + "了,请检查代码~");
return modelAndView;
}
}
第二种用法:配合@ModelAttribute做预设全局处理
@ControllerAdvice
public class GlobalExceptionHandling {
@ModelAttribute
public void presetParam(Model model) {
model.addAttribute("globalAttr", "this is a global attribute");
}
@ModelAttribute("myMap")
public Map<String, String> presetParam() {
// 将属性封装到一个map中
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
return map;
}
}
获取值:
@Controller
public class TestController {
@ResponseBody
@GetMapping("methodOne")
public String methodOne(Model model) {
// this is a global attribute
return (String) model.getAttribute("globalAttr");
}
@ResponseBody
@GetMapping("methodTwo")
public String methodTwo(@ModelAttribute("globalAttr") String globalAttr) {
// this is a global attribute
return globalAttr;
}
@ResponseBody
@GetMapping("methodThree")
public Map methodThree(@ModelAttribute("myMap") ModelMap modelMap, Model model) {
// 第一种方式,通过@ModelAttribute("myMap")指定
// 第二种方式:通过Model
Map<String,String> myMap = (Map<String,String>) model.getAttribute("myMap");
myMap.forEach((k, v) -> {
System.out.println(k + ":" + v);
});
return modelMap;
}
}
第三种用法:配合@InitBinder做请求参数预处理
@ControllerAdvice
public class GlobalExceptionHandling {
@InitBinder
public void processParam(WebDataBinder dataBinder){
/*
* 创建一个字符串微调编辑器
* 参数{boolean emptyAsNull}: 是否把空字符串("")视为 null
*/
StringTrimmerEditor trimmerEditor = new StringTrimmerEditor(true);
/*
* 注册自定义编辑器
* 接受两个参数{Class<?> requiredType, PropertyEditor propertyEditor}
* requiredType:所需处理的类型
* propertyEditor:属性编辑器,StringTrimmerEditor就是 propertyEditor的一个子类
*/
dataBinder.registerCustomEditor(String.class, trimmerEditor);
//同上,这里就不再一步一步讲解了
dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
}
}
测试:

@RestControllerAdvice:一个带返回体的@ControllerAdvice
注解的类,执行方法时是无法页面跳转的,等价于@ControllerAdvice+@ResponseBody,表示该方法返回json数据。
Demo1:发生运行时异常被全局异常处理器捕捉处理
@ControllerAdvice(value = {"com.zhixi.controller"}) // 指定那些包下的请求被全局异常处理
public class GlobalExceptionHandling {
@ResponseBody
@ExceptionHandler(RuntimeException.class)
public String handler() {
return "出错了";
}
}
返回字符数据到浏览器上面:

Demo2:某个注解修饰的类发生异常,被异常处理器捕捉处理
R:通用返回结果
import lombok.Data; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** * @ClassName R * @Author zhangzhixi * @Description 通用返回结果,服务器响应的数据最终都会封装成此对象 * @Date 2022-7-8 17:12 * @Version 1.0 */ @Data public class R<T> implements Serializable { private Integer code; //编码:1成功,0和其它数字为失败 private String msg; //错误信息 private T data; //数据 private Map<String, Object> map = new HashMap<>(); //动态数据 public static <T> R<T> success(T object) { R<T> r = new R<T>(); r.data = object; r.code = 1; return r; } public static <T> R<T> error(String msg) { R<T> r = new R<T>(); r.msg = msg; r.code = 0; return r; } public R<T> add(String key, Object value) { this.map.put(key, value); return this; } }
GlobalExceptionHandler:全局异常处理器
/**
* @ClassName GlobalExceptionHandler
* @Author zhangzhixi
* @Description 全局异常处理器
* @Date 2022-8-7 16:52
* @Version 1.0
*/
@RestControllerAdvice(annotations = {RestController.class, Controller.class})
@Slf4j
public class GlobalExceptionHandler {
/**
* 自定义业务异常处理器-菜品及套餐分类异常类
*
* @param exception 异常对象
* @return R结果对象
*/
@ExceptionHandler(Exception.class)
public R<String> exceptionHandler(Exception exception) {
log.error(exception.getMessage());
// 输出异常堆栈信息
return R.error(exception.getMessage().substring(exception.getMessage().lastIndexOf("[") + 1, exception.getMessage().lastIndexOf("]")));
}
}
测试用户注册,出现异常:


@Async与@EnableAsync:异步执行方法
@Async:这个注解标志着某个方法作作为异步执行候选者。这个注解可以加在类的层级上,表示该类的所有方法都被认为是异步执行。
@EnableAsync:启用spring异步方法执行功能,通常与@Configuration注解类同时使用,为整个springs application上下文启用注解驱动的异步处理功能。
具体的使用请参考:SpringBoot下@EnableAsync与@Async异步任务的使用
Swagger常用注解:
swagger的使用参考博客:https://www.cnblogs.com/zhangzhixi/p/14348822.html
controller中:
@Api(tags = "请求控制类") // 给controller类加注释
@ApiOperation("用户赋值请求") //给controller请求加注释
pojo实体类中:
@ApiModel("用户类") // 标注类的信息
@ApiModelProperty("用户名") // 标注属性信息
异步任务
@Async :在Service的类中或者方法中使用,表示这是一个异步的类或者方法
@EnableAsync:在程序的主入口类中添加,表示开启异步任务
@Transactional:事务
- *需要注意的是,在Service层方法上面加上这个注解,同时要在SpringBoot主启动类上面加上@EnableTransactionManagement,这样才能保持注解的生效。
事务的使用以及事务的失效场景:https://juejin.cn/post/6844904096747503629
- 调用方法导致的事务失效注意点
/* * 同一个类中,非事务方法A调用事务方法B,事务失效 * 同一个类中,事务方法A调用非事务方法B,事务具有传播性,事务生效 * 不同类中,事务方法A调用非事务方法B,事务生效 * 不同类中,非事务方法A调用事务方法B,方法B事务生效,如果B发生异常,方法A数据不会回滚 */
proagation属性
propagation 代表事务的传播行为,默认值为 Propagation.REQUIRED,其他的属性信息如下:
-
Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。( 也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务 ) -
Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。 -
Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。 -
Propagation.REQUIRES_NEW:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。( 当类A中的 a 方法用默认Propagation.REQUIRED模式,类B中的 b方法加上采用Propagation.REQUIRES_NEW模式,然后在 a 方法中调用 b方法操作数据库,然而 a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW会暂停 a方法的事务 ) -
Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。 -
Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。 -
Propagation.NESTED:和 Propagation.REQUIRED 效果一样。
isolation 属性
isolation :事务的隔离级别,默认值为 Isolation.DEFAULT。
- Isolation.DEFAULT:使用底层数据库默认的隔离级别。
- Isolation.READ_UNCOMMITTED
- Isolation.READ_COMMITTED
- Isolation.REPEATABLE_READ
- Isolation.SERIALIZABLE
timeout 属性
timeout:事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly 属性
readOnly:指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollbackFor 属性
rollbackFor:用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
noRollbackFor属性
noRollbackFor:抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。
SpringCache常用注解
地址:SpringBoot(SpringCache)整合Redis
@InitBinder:Controller中数据处理
- 由@InitBinder表示的方法,可以对WebDataBinder对象进行初始化。WebDataBinder是DataBinder的子类,用于完成由表单到JavaBean属性的绑定。
- @InitBinder方法不能有返回值,它必须声明为void。
- @InitBinder方法的参数通常是WebDataBinder,@InitBinder可以对WebDataBinder进行初始化
我们在接收参数的时候,对于基础的数据类型,比如接收string,int等类型,SpringMVC是可以直接处理的,但是对于其他复杂的对象类型,有时候是无法处理的,这时候就需要属性编辑器来进行处理(源数据为string)
Spring为我们提供了一些默认的属性编辑器:
第一种:org.springframework.beans.propertyeditors.CustomDateEditor就是其中一个,
第二种:继承java.beans.PropertyEditorSuppotr来根据具体的业务来定义自己的属性编辑器。
解决方法:手动配置数据格式处理:
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 严格限制日期转换
sdf.setLenient(false);
// true:允许输入空值,false:不能为空值
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
}

Shiro
关于Shiro的使用,详情可参考博客: https://www.cnblogs.com/zhangzhixi/p/17209095.html
@RequiresRoles:基于角色的权限认证
@RequiresPermissions:基于资源的权限认证
// 用来判断角色:具有 admin/user
@RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
// 用来判断权限字符串
@RequiresPermissions("user:update:01")
@RequestMapping("saveToPermissions")
public String saveToPermissions() {
return "redirect:/index.jsp";
}
RabbitMQ
具体的注解看使用到的是那种模型吧,这边有例子,比较容易理解:
https://gitee.com/zhang-zhixi/RabbitMQ-Study/tree/master/rabbitmq-02-springboot
@RabbitListener:设置监听的队列名称
可以加到类上或者方法上
@Queue:设置队列名称
@RabbitHandler:从队列中接收消息
// 生产者
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void test1() {
// 生产者向队列发送消息,需要注意的是,此处不会创建队列,是由消费者端创建的队列
rabbitTemplate.convertAndSend("hello","send Message To MQ");
}
// 消费者
/**
* @RabbitListener:设置监听的队列名称
* @Queue:设置队列名称,默认持久化、非独占、不自动删除队列
*/
@Component
@RabbitListener(queuesToDeclare = @Queue(value = "hello"))
public class ConsumerHello1 {
@RabbitHandler
public void receive1(String message) {
System.out.println("消费者消费到的消息是:" + message);
}
}
SpringCloud用到的注解:
@EnableDiscoveryClient:注册服务
该注解用于向使用consul或者zookeeper作为注册中心时注册服务
/**
* 服务发现
*/
@Resource
private DiscoveryClient discoveryClient;
/**
* 服务发现
*
* @return 服务清单
*/
@GetMapping(value = "/discovery")
public Object discovery() {
// 获取微服务列表的清单
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*****element: " + element);
}
// 通过微服务名称获取微服务实例
List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
for (ServiceInstance instance : instances) {
log.info(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
}
return this.discoveryClient;
}
@Accessors:链式注解
@Accessors(chain = true):开启链式编程
比如给属性字段赋值:dept.setD_no(1).setD_name("市场部").setD_source("db01");
@LoadBalanced:负载均衡
添加到要使用的bean上面:@LoadBalanced //配置负载均衡实现RestTemplate
@EnableEurekaClient:开启eureka客户端
通常使用在主启动类上
============熔断:Hystrix===============
@HystrixCommand:熔断后备方法
作用在方法上面,比如这个方法不会返回有效的数据抛出异常,就会去执行这个方法上面:HystrixCommand指定的方法
// 添加熔断的后备方法
@HystrixCommand(fallbackMethod = "hystrixGetDeptById")
@EnableCircuitBreaker:启用断路器
作用在主启动类上
============熔断:Hystrix===============
SpringBoot项目开发用到的配置:
# 关闭缓存
spring.thymeleaf.cache=false
# 项目虚拟目录,通过localhost/8080/res/静态资源名称访问,默认资源路径[/public,/static,/resources/META-INF/resources]
spring:
mvc:
static-path-pattern: /res/**
spring:
resources:
#重新指定静态资源的位置可以指定多个,用逗号分割即可。默认为类路径:[/META-INF/resources/, /resources/, /static/, /public/].
static-locations: [classpath:/zhang/]
# 指定国际化配置文件的真实位置
spring.messages.basename=iI18n.login
provider:服务提供者配置:
server: port: 8003 # mybatis配置 mybatis: type-aliases-package: com.zhixi.pojo config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml # spring配置 spring: application: name: springcloud-provider-dept # 三个服务名称一致 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/db03?userSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: zhixi158 # Eureka配置:配置服务注册中心地址 eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: springcloud-provider-dept-8003 #修改Eureka上的默认描述信息 # info配置 info: # 项目的名称 app.name: zhixi-springcloud # 公司的名称 company.name: com.zhixi.study

浙公网安备 33010602011771号