1.模型层注解
使用lombok,主要是编译时特性。
@Data
提供类的get、set、equals、hashCode、canEqual、toString方法
@Getter/@Setter
- 作用类上,生成所有成员变量的getter/setter方法
- 作用于成员变量上,生成该成员变量的getter/setter方法
//NonNull注解的属性不能为基本数据类型 如int应使用Integer
@Setter(value = AccessLevel.PUBLIC, onParam_ = {@NonNull})
public class Fruit {
private Integer id;
//属性上的注解会覆盖类上的相同注解
//编译后为protected setName没有非空判断
@Setter(value = AccessLevel.PROTECTED)
private String name;
}
@ToString
@ToString(of ={"name"})//of exclude
@EqualsAndHashCode
有继承关系时,子类不指定callSuper(生成的方法中是否调用父类的方法)属性编译会报错
解决方式一:注解加上callSuper = true
解决方式二(推荐):在src/mian/java下面加入配置类:lombok.config
config.stopBubbling=true
lombok.equalsAndHashCode.callSuper=call
编译后方法中调用父类方法:
public int hashCode() {
···
int result = super.hashCode(); //callSuper=true
···
}
public boolean equals(final Object o) {
···
} else if (!super.equals(o)) { //callSuper=true
···
}
@NoArgsConstructor,@AllArgsConstructor
生成无参构造和全参构造
@RequiredArgsConstructor
生成包含final和@NonNull注解的成员变量的构造器
@RequiredArgsConstructor
public class Orange extends Fruit{
@NonNull String color;
final String energy;
String weight;
}
编译后生成构造方法:
public Orange(@NonNull final String color, final String energy) {
if (color == null) {
throw new NullPointerException("color is marked non-null but is null");
} else {
this.color = color;
this.energy = energy;
}
}
@Builder
作用于类上,将类转变为建造者模式。编译后生成内部建造类。方便链式构造对象
Apple.builder().name("苹果").price(5.0).build();
@Cleanup @SneakyThrows
@Cleanup自动关闭资源,针对实现了java.io.Closeable接口的对象有效,如:典型的IO流对象
@SneakyThrows可以对受检异常进行捕捉并抛出
@SneakyThrows
public static String getFileText (String fileName) {
File file = new File("fileName");
StringBuilder sb = new StringBuilder();
int len;
byte[] byteArr = new byte[1024];
@Cleanup InputStream is = new FileInputStream(file);
while ((len = is.read(byteArr)) != -1) {
sb.append(new String(byteArr, 0, len));
}
return sb.toString();
}
编译后添加了关闭资源的代码
finally {
if (Collections.singletonList(is).get(0) != null) {
is.close();
}
}
@Synchronized
作用于方法级别,可以替换synchronize关键字或lock锁,用处不大
@Scope
- value
- singleton(默认)单例模式 -- 全局有且仅有一个实例。不需要通过proxyMode指定作用域代理类型
- prototype原型模式 -- 每次获取Bean的时候会有一个新的实例。Spring 在创建好交给使用者之后则不会再管理后续的生命周期。需要注意的是,如果未指明代理类型,即不使用代理的情况下,将会在容器启动时创建bean,那么每次并不会返回不同的实例,只有在指明作用域代理类型例如TARGET_CLASS后,才会在注入调用每次创建不同的实例。
- request -- 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。必须指定proxyMode作用域代理类型
- session -- 每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
- global session -- 作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义
- proxyMode
2.配置层注解
@SpringBootApplication
= @SpringBootConfiguration+ @EnableAutoConfiguration + @ComponentScan
@SpringBootConfiguration
- 等同于@Configuration,代替 applicationContext.xml 配置文件。标识这个类可以使用Spring IoC容器作为bean定义的来源。
- 配合@Bean。Spring会将@Bean注解的方法返回的对象注册到Spring应用程序上下文中
@SpringBootApplication //包含@SpringBootConfiguration
public class MyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
Fruit fruit = (Fruit) context.getBean("defaultFruit"); //从上下文能获取配置类中注册的bean
System.out.println(fruit);
}
@Bean
public Fruit defaultFruit() {
Fruit fruit = new Fruit(1, "配置默认水果");
return fruit;
}
}
对应于XML中:
<beans>
<bean id = "defaultFruit" class="com.zsc.domain.Fruit">
<property name="id" >1</property>
<property name="name" >配置默认水果</property>
</bean>
</beans>
@EnableAutoConfiguration
- 能够自动配置spring的上下文,“猜测”和配置你想要的bean类,通常会自动根据你的类路径和你的bean定义自动配置。例如引入了spring-boot-starter-web,Spring将自动引入添加Tomcat和Spring MVC相关jar依赖
- 简化了导入二方包bean的成本。提供一个二方包给其他应用使用,只需要在二方包里将对外暴露的bean定义在spring.factories中就好了。
- exclude属性:排除不需要的bean
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
@ComponentScan
会自动扫描指定包下的全部标有@Component的类(包括其子注解@Controller,@Service,@Repository),并注册成bean。等价于applicationContext.xml配置文件中的配置项<context:component-scan>。
@ServletComponentScan
Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码
@WebFilter
- 注册过滤器,启动类添加@ServletComponentScan注解
@WebFilter(urlPatterns = "/dtb/*", filterName = "opertaorFilter")
public class OperatorFilter implements Filter {
}
- 过滤器注入
@WebFilter方式注册的Filter,无法通过@Autowired方式来注入Spring的bean。 - 过滤器优先级
- 通过过滤器名称和设置@Order的方法都是不行的。
- 通过 WebFillter方式注册,默认优先级为2147483647,相同优先级的情况下,根据名字先后顺序来决定。
- 可以通过过滤器的类名进行约定排序,但需要限制类名。建议用FilterRegistrationBean进行设置。
@WebServlet
@WebServlet(name="TestServlet",urlPatterns="/test")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("doGet");
}
}
@EnableTransactionManagement
开启事务管理
@EnableCaching
这个注解是spring framework中的注解驱动的缓存管理功能,其作用相当于spring配置文件中的cache manager标签
@EnableScheduling
开启定时任务
3.Controller层注解
@Component
- 把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>
- 子注解有@Controller,@Service,@Repository。
- 当组件不好归类的时候,我们可以使用这个注解进行标注
@Controller
@Controller 表明这个类是一个控制器类,如果不在method中注明请求的方式,默认是拦截get和post请求,请求完成后转向一个视图解析器
@ResponseBody
返回结果直接写入HTTP response body
@RequestMapping("/login")
@ResponseBody
public User login(User user){
return user;
}
//效果等同于
@RequestMapping("/login")
public void login(User user, HttpServletResponse response){
response.getWriter.write(JSONObject.fromObject(user).toString());
}
@RestController
= @Controller + @ResponseBody
- 我们现在前后端分离,一般返回json格式报文,需要@Controller与@ResponseBody搭配,故使用@RestController 。
- @RestController 只返回对象,对象数据直接以 JSON 或 XML 形式写入 HTTP 响应中
- 当返回为基础数据类型或String时,返回给前端仍为基础数据类型或String,如下:
@GetMapping("ok")
public boolean ok() {
return true;
}
@RequestMapping
- 指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置
- 可作用于类或方法上,路径会叠加,如下:
@RestController
@RequestMapping("fruit")
public class FruitController {
@RequestMapping((value="query ",method= RequestMethod.GET ) //会拦截 /fruit/query 的请求
public Fruit query(){}
}
- 建议使用Rest风格注解,较为简洁:
@GetMapping(value =“”)
@PostMapping(value =“”)
@PutMapping(value =“”)
@DeleteMapping(value =“”)
@RequestBody @PathVariable @RequestParam
- @RequestBody主要用来接收前端传递给后端的json字符串(请求体中的数据),一个请求只有一个
- @PathVariable为路径变量注解,一个请求可以有多个
- @RequestParam为请求参数注解,一个请求可以有多个
使用如下:
@RestController
@RequestMapping("fruit")
public class FruitController {
@PostMapping("add")
public void addFruit(@RequestBody Fruit fruit){
System.out.println("请求json:" + fruit.toString());
}
@GetMapping("query/{id}")
public void queryById(
@PathVariable String id,
@RequestParam(required = false) String name //required = false表示参数name可以不传
) {
System.out.println("ID:" + id);
System.out.println("参数name:" + name);
}
对于请求http://localhost:8080/fruit/query/14?name=指定水果,输出如下
ID:14
参数name:指定水果
@Autowired
- 自动装配:将Spring容器中的bean自动的和我们需要这个bean的类组装在一起。
- @Autowired为按照type注入,@Resource默认通过name属性去匹配bean,找不到再按type去匹配
- 可以注入数组或集合,例如
public class FruitController {
/**spring会从ApplicationContext中搜寻符合指定类型的所有bean*/
@Autowired
AppleService[] appleServiceArr;
@Autowired
Set<AppleService> appleServiceSet;
@Autowired
//key的类型必须为String,注入后值为bean的名称 appleService
//value类型即为想要注入的bean类,所有类型匹配的bean会被注入进来; com.zsc.domain.AppleService@18cc679e
Map<String, AppleService> appleServiceMap;
}
@ControllerAdvice
@RestControllerAdvice 是Controller的切面,结合@ExceptionHandler实现全局异常捕获和处理
@CrossOrigin
@CrossOrigin(origins = "", maxAge = 1000) 这个注解主要是为了解决跨域访问的问题。这个注解可以为整个controller配置启用跨域,也可以在方法级别启用。
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class FileController {
}
4.Service层注解
@Service
表明这个类是一个业务层的组件
@Transactional
- 通过这个注解可以声明事务,可以添加在类上或者方法上。
- 在spring boot中 不用再单独配置事务管理,一般情况是我们会在servcie层添加了事务注解,即可开启事务。要注意的是,事务的开启只能在public 方法上。
5.持久层注解
@Repository
作为DAO对象,管理操作数据库的对象
DBO注解
@Entity
@Table(name = "zsc1_apple_t")
public class AppleDbo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "apple_name")
private String name;
@Column(name = "apple_price")
private Double price;
@Transient //表示此数据不在数据库表里建立属性
private String temp;
}
6.其他注解
@Aspject
把当前类标识为一个切面供容器读取。
@Component
@Aspect
public class LogAspect {
@Before("execution(* com.zsc.controller.*.*(..))")
public void beforeMethod(JoinPoint jp){
Signature signature = jp.getSignature();
Object[] args = jp.getArgs();
System.out.println("【前置通知】:方法" + signature.getName() + ",参数:"+ Arrays.asList(args));
}
@After("execution(* com.zsc.controller.*.*(..))")
public void afterMethod(JoinPoint jp){
Signature signature = jp.getSignature();
Object[] args = jp.getArgs();
System.out.println("【后置通知】:方法" + signature.getName() + ",参数:"+ Arrays.asList(args));
}
@Scheduled
定时任务
- fixedRate 每隔多长时间执行
- fixedDelay 上一次任务完成后,隔多长时间执行
- cron cron表达式,指定时间执行
@Component
public class Jobs {
//表示方法执行完成后5秒
@Scheduled(fixedDelay = 5000)
public void fixedDelayJob() throws InterruptedException {
System.out.println("fixedDelay 每隔5秒" + new Date());
}
//表示每隔3秒
@Scheduled(fixedRate = 3000)
public void fixedRateJob() {
System.out.println("fixedRate 每隔3秒" + new Date());
}
//表示每天8时30分0秒执行
@Scheduled(cron = "0 0,30 0,8 ? * ? ")
public void cronJob() {
System.out.println(new Date() + " ...>>cron....");
}
}
@Cahing 缓存相关注解
- @Cacheable 创建缓存
- @CachePut 更新缓存
- @CacheEvict 清除缓存
单元测试注解
@runWith
指用SpringRunner来运行,其中SpringRunner继承类SpringJUnit4ClassRunner
@SpringBootTest
通过SpringApplication在测试中创建ApplicationContext
@WebAppConfiguration
@WebAppConfiguration:测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的;value指定web应用的根;
@MockBean
模拟相应对象,使用mock对象代替原来spring的bean,然后模拟底层数据的返回,而不是调用原本真正的实现。
@AutoConfigureMockMvc