Spring Boot starter
Spring Boot大大简化了项目初始搭建以及开发过程spring boot 在配置上相比spring要简单许多, 其核心在于spring-boot-starter, 在使用spring boot来搭建一个项目时, 只需要引入官方提供的starter, 就可以直接使用, 免去了各种配置。starter简单来讲就是引入了一些相关依赖和一些初始化的配置。
Spring官方提供了很多starter,第三方也可以定义starter。为了加以区分,starter从名称上进行了如下规范:
-
Spring官方提供的starter名称为:spring-boot-starter-xxx
例如Spring官方提供的spring-boot-starter-web
-
第三方提供的starter名称为:xxx-spring-boot-starter
例如由mybatis提供的mybatis-spring-boot-starter
starter原理
Spring Boot之所以能够帮我们简化项目的搭建和开发过程,主要是基于它提供的起步依赖和自动配置。
1.起步依赖
起步依赖,就是将具备某种功能的坐标打包到一起,可以简化依赖导入的过程,例如,导入spring-boot-starter-web这个starter,则和web开发相关相关的jar包都一起导入到项目中了
2.自动配置
自动配置,无须手动配置xml,自动配置并管理bean,可以简化开发过程。
自动配置涉及到
- 基于java代码的bean配置
- 自动配置条件依赖
- bean参数获取
- bean的发现
- bean的加载
自定义starter
案例一:
开发starter
- 创建spring-boot-starter-parent的maven项目导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
- 创建配置属性类HelloProperties(通常用于封装配置文件里面的配置参数的)
package cn.itcast.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 读取yml文件属性参数
*/
@ConfigurationProperties(prefix = "hello")//如果报错可以先忽略
public class HelloProperties{
private String name;
private String address;
@Override
public String toString() {
return "HelloProperties{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
- 创建服务类HelloService
package cn.itcast.service;
public class HelloService {
private String name;
private String address;
public HelloService(String name, String address) {
this.name = name;
this.address = address;
}
public String sayHello(){
return "你好!我的名字叫 " + name + ",我来自 " + address;
}
}
- 创建自动配置类HelloServiceAutoConfiguration
package cn.itcast.config;
import cn.itcast.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置类,基于java代码的bean配置
*/
@Configuration//表示当前是一个配置类
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
private HelloProperties helloProperties;
// 通过构造方法注入配置属性对象HelloProperties
public HelloServiceAutoConfiguration(HelloProperties helloProperties){
this.helloProperties=helloProperties;
}
// 实例化HelloService并放入ioc中
@Bean
@ConditionalOnMissingBean
public HelloService helloService(){
return new HelloService(helloProperties.getName(),helloProperties.getAddress());
}
}
- 在resources目录下创建META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.itcast.config.HelloServiceAutoConfiguration
#EnableAutoConfiguration是一个注解作用是找到自动配置类
将该项目打成jar包
使用starter
- 创建新的maven工程
test-hello-spring-boot-starter
导入maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mubai</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
- 创建application.yml文件
server:
port: 8080
hello:
name: mubai
address: hefei
- 创建HelloController
package org.mubai.controller;
import cn.itcast.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
//HelloService在我们自定义的starter中的自动配置类里面创建在ioc中已经完成了自动配置,所以此处可以直接注入
@Autowired
private HelloService helloService;
@GetMapping("/say")
public String sayHello(){
return helloService.sayHello();
}
}
- 创建启动类
package cn.itcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class,args);
}
}
启动访问接口
案例二:通过自动配置来创建一个拦截器对象,通过此拦截器对象来实现记录日志功能。
开发starter
- 在hello-spring-boot-starter的pom.xml文件中追加如下maven坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
- 自定义MyLog注解(不是所有的接口都拦截,只有加入这个注解的接口才会被拦截)
package cn.itcast.log;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义日志注解
*/
@Target(ElementType.METHOD)//加在方法上的注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
/**
* 方法描述
*/
String desc() default "";
}
- 自定义日志拦截器MyLogInterceptor
package cn.itcast.log;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.lang.reflect.Method;
/**
* 自定义日志拦截器
*/
public class MyLogInterceptor extends HandlerInterceptorAdapter {
private static final ThreadLocal<Long> startTimeThreadLocal=new ThreadLocal<>();//多线程访问共享变量的方法
//在controller方法前执行此方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod=(HandlerMethod)handler;
Method method = handlerMethod.getMethod();//获取被拦截的方法对象
MyLog annotation = method.getAnnotation(MyLog.class);//获得方法上有没有MyLog注解
if(annotation!=null){
// 如果为空则说明没有获取到注解
long l = System.currentTimeMillis();
startTimeThreadLocal.set(l);//记录此刻时间
}
return true;//放行
}
//在controller方法后执行此方法
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();//获得被拦截的方法对象
MyLog myLog = method.getAnnotation(MyLog.class);//获得方法上的注解
if (myLog != null) {
//方法上加了MyLog注解,需要进行日志记录
long endTime = System.currentTimeMillis();
Long startTime = startTimeThreadLocal.get();
long optTime = endTime - startTime;
String requestUri = request.getRequestURI();
String methodName = method.getDeclaringClass().getName() + "." +
method.getName();
String methodDesc = myLog.desc();
System.out.println("请求uri:" + requestUri);
System.out.println("请求方法名:" + methodName);
System.out.println("方法描述:" + methodDesc);
System.out.println("方法执行时间:" + optTime + "ms");
}
super.postHandle(request, response, handler, modelAndView);
}
}
- 创建自动配置类MyLogAutoConfiguration,用于自动配置拦截器、参数解析器等web组件
package cn.itcast.config;
import cn.itcast.log.MyLogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 配置类,用于自动配置拦截器、参数解析器等web组件
*/
@Configuration
public class MyLogAutoConfiguration implements WebMvcConfigurer {
//注册自定义日志拦截器//此方法是接口中的方法,不需要配置bean,是专门用来添加拦截器的方法,拦截器会被自动的序列化,加入ioc中
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyLogInterceptor());
}
}
- 在spring.factories中追加MyLogAutoConfiguration配置(告诉boot现在有一个这样的配置)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.itcast.config.HelloServiceAutoConfiguration,\
cn.itcast.config.MyLogAutoConfiguration
- 使用starter