• 介绍
    • 减少配置, 习惯大于配置
    • 支持groovy, gradle
  • 命令
    • java -jar xxx.jar
      • -server.port=8080 # —后内容,相当于application.yml设置
      • -spring.profiles.active=two # 选择applicaton-two.yml配置
  • 基础文件
    • 目录
      • src
        • main
          • java
            • com.outrun
              • XxxApplication
          • resources
            • static/
            • templates/
            • application.properties
            • application.yml
          • webapp
            • WEB-INF
        • test
          • java
            • com.outrun
              • XxxApplicationTests
      • pom.xml
    • XxxApplication.java # 程序入口
      • @SpringBootApplication # 类,组合@Configuration, @EnableAutoConfiguration, @ComponentScan
        • @EnableAutoConfiguration根据jar包依赖自动配置
        • 扫描该注解同级下级包的Bean
    • application.yml # application.yml或application.properties, 放在src/main/resources或config目录下
    • pom.xml
  • 配置
    • 区分环境
      • application-{profile}.properties # profile比如是dev, test, prod
      • 设置spring.profiles.active=dev来区分
    • 加载顺序 # 为了外部人员维护,可覆盖定义
      • 命令行
      • SPRING_APPLICATION_JSON环境变量, json格式
      • java:comp/env的JNDI属性
      • java系统属性 # System.getProperties()查看
      • 系统环境变量
      • random.*配置的随机属性
      • jar包外文件名, 如application-{profile}.properties
      • jar包内文件名
      • @Configuration注解类中,@PropertySource修改的属性
      • SpringApplication.setDefaultProperties定义的内容
    • application.yml
      • — # ---分隔多个配置,这里相当于建立了application-two.yml文件
      • spring:
        • profiles: two

      • spring:
        • profiles
          • active: dev # 配置环境, 加载applicaton-dev.yml
        • application:
          • name: app1
    • pom.xml
      • <packaging>jar</packaging> # 不用war包部署, 嵌入了tomcat, jar可服务 - <parent> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-parent</artifactId> # 提供spring boot基础依赖和默认配置 - <relativePath/> # 从仓库查找parent - </parent> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <java.version>1.8</java.version> - </properties> - <dependencies> - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> # 方便启动停止应用, 如mvn spring-boot:run - </plugin> - </plugins> - </build>- 注解
    • @SpringBootApplication # spring boot 启动类
      • 组合了@Configuration, @EnableAutoConfiguration, @ComponentScan
    • ApplicationRunner # 继承该类,注解@Component, 随容器启动运行
      • run()
  • 插件
    • maven
      • 命令
        • mvn spring-boot:run
      • pom.xml
        • <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> # 方便启动停止应用, 如mvn spring-boot:run - </plugin>- 组件
    • starter POMs # spring-boot-starter开头的组件
  • 子域
    • NamedContextFactory
      • class Spec1 implements NamedContextFactory.Specification {
        • @Override
        • public String getName(){}
        • @Override
        • public Class<?>[] getConfiguration(){}
      • }
      • public class MyFactory extends NamedContextFactory {
        • public MyFactory(Class<?> clazz) {
          • super(clazz, “my”, “my.name”)
        • }
      • }
      • @Configuration
      • public class Config0 {
        • @Bean
        • Bean0 getBean(){
          • return new Bean0()
        • }
      • }
      • parent = new AnnotationConfigApplicationContext()
      • parent.register(Config0.class)
      • parent.refresh()
      • factory = new MyFactory(Config00.class)
      • factory.setApplicationContext(parent)
      • spec1 = new Spec1(“1”, new Class[]{Config1.class})
      • factory.setConfigurations(List.of(spec1))
      • factory.getInstance(“1”, Bean0.class) // 子域共享
      • factory.getInstance(“1”, Bean00.class) // 子域复制
      • factory.getInstance(“1”, Bean1.class)
    • spring
      • 配置
        • 随机数用${random}
          • ${random.value} 字符串
          • ${random.int} int
          • ${random.long} long
          • ${random.int(10)} 10以内int
          • ${random.int[10,20]} 10到20 int
        • pom.xml
          • <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-configuration-processor</artifactId> - <optional>true</optional> - </dependency> - application.yml
          • aa
            • bb: 1 # 可用properties类管理属性
          • xxx: 1 # 自定义value
            • 配置文件中用”${xxx}“引用
            • 类中用@Value(”${xxx}“)注入到属性
            • SpEL中用”#{xxx}“引用
        • AaProperties.java
          • @Component
          • @ConfigurationProperties(prefix = “aa”)
          • public class AaProperties {
            • private String bb;
            • …getter和setter…
          • }
        • 注解
          • @Configuration
          • @PropertySource(value = “classpath:test.properties”) # 加载文件, 配合@ConfigurationProperties注入属性
          • @EnableConfigurationProperties({ConfigBean.class, User.class}) # 加载bean, 配合@Autowired注入
      • 基础
        • 注解
          • @Value(”${xxx}”)
          • @Autowired # 装载bean
          • @Bean # 实例化Bean, 属性名为方法名
            • @Bean
            • public RestTemplate restTemplate() {
              • return new RestTemplate();
            • }
            • 相当于
            • RestTemplate restTemplate = new RestTemplate();
          • @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) # 生命周期
            • singleton # 单例
            • prototype # 多例
            • request # web程序ContextApplication用, 随请求创建
            • session # web程序ContextApplication用, 随session创建
            • global session # porlet的global用, 其它用降级为session
          • @EventListener(XxxEvent.class) # 修饰方法, 外部publishEvent()时触发
      • 实体
        • 注解
          • @Entity # 修饰bean类
          • @Id # id属性
          • @GeneratedValue(strategy=GenerationType.AUTO) # 自增属性
          • @Column(nullable = false, unique = true)
      • 组件
        • 注解
          • @Component
          • @ConfigurationProperties(prefix = “my”) # 注入properties对应名称的属性
      • dao
        • 注解
          • @Repository # 修饰类
      • service
        • 注解
          • @Service # 修饰类
          • @PostConstruct # 修饰方法, 加载servlet时, init()前执行
          • @PreDestroy # 修饰方法, 销毁servlet时, destroy()后执行
      • controller
        • 注解
          • @Controller # 修饰类
    • 测试
      • pom.xml
        • <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <scope>test</scope> - </dependency> - 注解
        • @Before
        • @Test
        • @RunWith(SpringRunner.class) # 修饰类, 测试spring
        • @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) # 修饰类, 测试spring boot
        • @LocalServerPort # 注入端口号
        • @AutoConfigureMockMvc # 使用mockMvc, 用@Autowired注入MockMvc
        • @WebAppConfiguration # 模拟ServletContext
      • XxxApplicationTests.java # junit测试
        • @RunWith(SpringJUnit4ClassRunner.class)
        • @SpringApplicationConfiguration(classes = XxxApplication.class)
        • @WebAppConfiguration
        • public class XxxApplicationTests {
          • private MockMvc mvc;
          • @Before
          • public void setUp() throws Exception {
            • mvc = MockMvcBuilders.standaloneSetup(new XxxController()).build();
          • }
          • @Test
          • public void hello() throws Exception {
            • mvc.perform(MockMvcRequestBuilders.get(“/hello”).accept(MediaType.APPLICATION_JSON))
              • .addExpect(status().isOk())
              • .addExpect(content().string(equalTo(“hello”)));
          • }
        • }
    • 数据库
      • pom.xml
        • spring-boot-starter-jdbc
        • spring-boot-starter-data-jpa # spring data JPA
      • application.yml
        • jpa:
          • generate-ddl: false
          • show-sql: true
          • hibernate:
            • ddl-auto: none # create时, 第一次create之后update
        • datasource:
          • platform: h2
          • schema: classpath:schema.sql # 建表
          • data: classpath:data.sql # 数据
      • 注解
        • @Transactional # 修饰方法,开启事务,或在事务中
    • mybatis
      • pom.xml
        • <!— mybatis - <dependency> - <groupId>org.mybatis.spring.boot</groupId> - <artifactId>mybatis-spring-boot-starter</artifactId> - <version>1.1.1</version> - </dependency> - <!— mysql - <dependency> - <groupId>mysql</groupId> - <artifactId>mysql-connector-java</artifactId> - <version>5.1.21</version> - </dependency> - application.yml
        • spring:
          • datasource:
            • url: jdbc:mysql://127.0.0.1:3306/outrun?characterEncoding=UTF-8
            • username: root
            • password: a
            • driver-class-name: com.mysql.jdbc.Driver
          • jpa:
          • hibernate:
            • ddl-auto: update # 新建连接必要
        • mybatis:
          • mapper-locations: classpath:mapper/*.xml # 指定mapper.xml位置
      • mapper.xml # 用mbg生成
        • <?xml version=“1.0” encoding=“UTF-8”?> - <!DOCTYPE mapper PUBLIC ”-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd”> - <mapper namespace=“com.outrun.erp.mapper.UserMapper”> - <resultMap id=“BaseResultMap” type=“com.outrun.erp.entities.User”> - <id column=“id” jdbcType=“BIGINT” property=“id” /> - <result column=“name” jdbcType=“VARCHAR” property=“name” /> - </resultMap> - <select id=“selectUserById” parameterType=“long” resultMap=“UserMap”> - SELECT name FROM user WHERE id=#{userId}
          • </select> - <insert id=“inserUser”> - <selectKey keyProperty=“id” resultType=“int” order=“BEFORE”> - select field1 from seq1
            • </selectKey> - </insert> - <sql id=“userColumns”> - ${alias}.id, ${alias}.username
          • </sql> - <select id=“selectColumns” resultType=“map”> - select - <include refid=“userColumns”><property name=“alias” value=“tb1”/></include> - from tb1
          • </select> - <select id=“dynamicSql” resultType=“User”> - select * from user
            • where state = 0
            • <if test=“title != null”> - and title like #{title}
            • </if> - <choose> - <when test=“title != null”> - and title like #{title}
              • </when> - <when test=“author != null and author.name != null”> - and author_name like ${author.name}
              • </when> - <otherwise> - and featured = 1
              • </otherwise> - </choose> - <foreach item=“item” index=“index” collection=“list” open=”(” separator=”,” close=”)”> - #{item}
            • </foreach> - <trim prefix=“where” prefixOverrides=“and | or”> - …
            • </trim> - <bind name=“a” value=”’%’ + _data.getTitle() + ’%’” /> - select * from blog
            • where title like #{a}
          • </select> - <update> - update User - <set> - <if test=“username != null”>username=#{username},</if> - </set> - </update> - <cache> # 该命名空间缓存 - <cache-ref> # 引用其它命名空间缓存 - <delete> - <resultMap> - <constructor> # 构造方法 - <idArg> # id参数, 标记id帮助提高性能 - <arg> # 普通参数 - </constructor> - <id> # 标记id帮助提高性能 - <result> # 普通字段 - <association> # 关联 - <collection> # 结构体 - <discriminator> # 自动映射 - </resultMap> - </mapper> - mapper/UserMapper
        • @Mapper # 如果扫描mapper.xml,不用加@Mapper
        • public interface UserMapper {
          • List selectUserById(@Param(“userId”) long userId)
          • @Select(“select * from user”)
          • List findAll();
        • }
      • entities/User
        • public class User {
          • private Integer id;
          • private String name;
          • …getter, setter…
        • }
      • 注解
        • @Table(name = “user”) # 修饰类,指定表
        • @Id # 修饰属性, 指定主键
        • @Column(name = “name”) # 修饰属性, 指定字段
        • @Mapper # 修饰类
        • @Select(“select * from user”) # 修饰方法
        • @Param(“userId”) # 修饰参数
      • api
        • SqlSessionFactory
          • build
          • openSession # 重载事务方法
        • SqlSesion
          • selectOne()
          • selectList()
          • selectMap()
          • insert()
          • update()
          • delete()
          • commit()
          • rollback()
          • clearCache()
          • close()
        • Mapper
          • o
          • @Insert(“insert into tb1(id, name) values(#{id}, #{name})”)
          • @SelectKey(statement=“next value”, keyProperty=“id”, before=true, resultType=int.class)
          • int insertTable1(String name)
        • SQL
          • INSERT_INTO()
          • VALUES()
          • o
          • new SQL(){{
            • SELECT(“a.name”);
            • SELECT(“a.age”);
            • FROM(“tb1 a”);
            • WHERE(“a.name like ?”);
          • }}.toString()
        • LogFactory
          • useSlf4jLogging()
          • useLog4jLogging()
          • useStdOutLogging()
    • web
      • 用的spring mvc
      • pom.xml
        • <dependency> - <groupId>org.springframework.boot</groupId> # web模块, 有tomcat, spring mvc - <artifactId>spring-boot-starter-web</artifactId> # 测试模块, 有JUnit, Hamcrest, Mockito - </dependency> - application.yml
        • server
          • port: 8080 # 默认8080
          • servlet
            • context-path: /hello # uri前缀
      • 静态资源
        • 默认映射public, resources, static到/
      • 注解
        • 控制器
          • @RestController # 修饰类, 组合@Controller与@responseBody
          • @RequestMapping(“/index”) # 修改类或方法, url
            • @GetMapping(”/{id}”) # 相当于@RequestMapping(method=RequestMethod.GET)
            • @PostMapping
            • @PutMapping
            • @DeleteMapping
            • @PatchMapping
          • @CrossOrigin # 修饰方法, 允许跨域
          • @RequestBody # 修饰方法, 解析body到参数
          • @PathVariable Long id # 修饰参数, 接收url参数
      • 内置对象
        • ServerProperties # 单例可@Autowired, 存端口之类属性
      • 自实现
        • XxxController.java
          • @RestController
          • public class HelloController {
            • @RequestMapping(“/hello”)
            • public String index() {
              • return “hello”;
            • }
          • }
    • 日志
      • application.yml
        • logging:
          • level:
            • root: INFO
            • org.hibernate: INFO
            • org.hibernate.type.descriptor.sql.BasicBinder: TRACE
            • org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
      • 注解
        • @Slf4j # 修饰类,其中可直接用log变量
        • @EnableSwagger2 # 修饰类
        • @Api(tags = "") # 修饰类, 文档
        • @ApiModel("") # 修饰类
        • @ApiModelProperty(”) # 修饰属性
        • @ApiOperation(value="", notes="") # 修改方法, 文档
        • @ApiIgnore # 修饰方法, 文档忽略
    • jackson
      • 注解
        • @JsonInclude # 修饰类, 序列化时包含
          • @JsonInclude(JsonInclude.Include.NON_EMPTY) # null或""时不序列化
        • @JsonIgnore # 修饰属性
    • Scheduled
      • scheduled
        • 注解
          • @Scheduled # 修饰方法, 定时调度
            • @Scheduled(initialDelay = 1000, fixedRate = 1000)
          • @Configuration
          • implements SchedulingConfigurer # 配置类
            • configureTasks(ScheduledTaskRegistrar)
              • registrar.setScheduler(Executors.newScheduledThreadPool(2)); # worker池
      • async
        • 注解
          • @Async # 修饰方法, 异步调用
          • implements AsyncUncaughtExceptionHandler # 处理@Async异常
            • @Override
            • public void handleUncaughtException()
          • @Configuration
          • @EnableAsync
          • implements AsyncConfigurer
            • @Bean
            • @Override
            • public Executor getAsyncExecutor()
            • @Override
            • public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() # 处理无返回值@Async方法异常
              • return handler
        • 使用
        • @Async
        • Future fetch(){
          • return new AsyncResult("")
        • }
        • future = fetch()
        • try{
          • future.get()
        • }
    • 热部署
      • pom.xml
        • <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-devtools</artifactId> - <optional>true</optional> # 热部署 - </dependency> - application.yml
        • spring:
          • devtools:
          • restart:
            • enabled: true
            • additional-paths: src/main/java
    • jsp
      • pom.xml
        • <!— servlet依赖. - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>jstl</artifactId> - </dependency> - <!— tomcat的支持. - <dependency> - <groupId>org.apache.tomcat.embed</groupId> - <artifactId>tomcat-embed-jasper</artifactId> - <scope>provided</scope> - </dependency> - application.yml
        • spring:
          • mvc:
          • view:
            • prefix: /WEB-INF/views/
            • suffix: .jsp
      • controller类
        • @Controller
        • public class XxxController {
          • @RequestMapping(“/xxx”)
          • public String xxx(Model m) {
            • m.addAttribute(“a”, 1);
            • return “view1”;
          • }
        • }
      • src/main/webapp/WEB-INF/views/view1.jsp
        • <%@ page language=“java” contentType=“text/html; charset=utf-8” pageEncoding=“utf-8”%> - jsp ${a}
    • lombok
      • 注解
        • @Builder # 修饰类, 可build方式设置属性
        • @Getter # 修饰类, 生成getter
        • @Setter # 修饰类, 生成setter
        • @ToString # 修饰类, 生成toString方法
        • @Data # 修饰类, 注入getter, setter, toString
        • @NoArgsConstructor # 修饰类, 生成无参构造方法
        • @AllArgsContructor # 修饰类, 生成带所有参数的构造方法
        • @RequiredArgsConstructor # 修饰类, 生成带常量、@NotNull修饰变量参数的构造方法
          • @RequiredArgsConstructor(onConstructor_ = @Autowired) # 构造类时,自动对private final 属性@Autowire
    • remote shell
      • pom.xml
        • spring-boot-starter-remote-shell
    • actuator
      • pom.xml
        • <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - </dependency> - 原生端点
        • 应用配置类
          • /autoconfig # 自动化配置详情
            • positiveMatches # 成功
            • negativeMatches
          • /beans # 所有bean
          • /configprops # 属性
          • /env # 环境属性
          • /mappings # spring mvc映射关系
          • /info # 自定义信息,默认为空,用info前缀定义
        • 度量指标
          • /metrics # 程序信息,内存、线程、gc等
            • nonheap.* # 非堆内存
            • gauge.* # http请求性能,如gauge.response表示上次延迟
            • counter.* # 记录累计,如counter.status.200表示返回200的次数
          • /metrics/{name} # 查看某项
            • /metrics/mem.free
          • /health # 启动状态,磁盘空间
            • DiskSpaceHealthIndicator # 低磁盘空间
            • DataSourceHealthIndicator # DataSource连接是否可用
            • MongoHealthIndicator
            • RabbitHealthIndicator
            • RedisHealthIndicator
            • SolrHealthIndicator
          • /dump # 线程信息
          • /trace # 跟踪信息
        • 操作控制 # 用属性配置开启
          • /shutdown # 关闭端点
            • 通过endpoints.shutdown.enabled=true开启
      • 自定义counter统计
        • @Autowired
        • private CounterService counterService;
        • counterService.increment(“didispace.hello.count”)
      • 自定义health检测器
        • @Component
        • public class RocketMQHealthIndicator implements HealthIndicator {
          • private int check(){}
          • @Override
          • public Health health() {
            • int errorCode = check();
            • if (errorCode !=0) {
              • return Health.down().withDetail(“Error Code”, errorCode).build();
              • return Health.up().build();
            • }
          • }
        • }
    • spring boot admin
      • application.yml
        • spring:
          • application:
            • name: erp-admin-server
          • boot:
            • admin:
              • routes:
                • endpoints: env,metrics,dump,jolokia,info,configprops,trace,logfile,refresh,flyway,liquibase,heapdump,loggers,auditevents,hystrix.stream
        • endpoints:
          • health:
            • sensitive: false
            • enabled: true
          • actuator:
            • enabled: true
            • sensitive: false
          • beans:
            • sensitive: false
            • enabled: true
    • spring initializer
      • 介绍
        • 生成spring基础项目
    • spring security
      • 配置
        • application.yml
          • security:
            • basic:
              • enabled: false # 禁用security
      • 注解
        • @EnableWebSecurity # 修饰WebSecurityConfigurerAdapter, 开启web验证
        • @EnableGlobalMethodSecurity(prePostEnabled = true) # 修饰WebSecurityConfigurerAdapter, 开启方法验证
        • @PreAuthorize # 修饰controller方法
      • api
        • Subject # 主体数据结构, 如用户
        • SecurityManager # 安全管理器, 管理所有subject
        • UserDetails
          • getAuthorities()
          • getUsername()
          • getPassword()
          • isAccountNonExpired()
          • isAccountNonLocked()
          • isCredentialsNonExpired()
          • isEnabled()
        • GrantedAuthority
          • getAuthority()
        • WebSecurityConfigurerAdapter
          • configure(HttpSecurity) # 验证请求
          • configure(AuthenticationManagerBuilder) # 验证数据,需要授权服务配置AuthenticationManager
            • userDetailService
            • passwordEncoder
          • authenticationManagerBean() # 指定管理bean
    • spring security oauth2
      • pom.xml
        • spring-cloud-starter-oauth2
      • 结构
        • OAuth2 Provider
          • Authorization Service # 授权服务
          • Resource Service # 资源服务
          • Spring Security过滤器
            • /oauth/authorize # 授权
            • /oauth/token # 获取token
      • 授权服务
        • applicatoin.yml # server
          • security:
            • oauth2:
              • resource:
                • filter-order: 3
        • 注解
          • @EnableAuthorizationServer # 修饰AuthorizationServerConfigurerAdapter, 开启授权服务
        • api
          • AuthorizationServerConfigurerAdapter # 授权服务配置
            • configure(ClientDetailsServiceConfigurer) # 客户端信息
              • clientId
              • secret
              • scope
              • authorizedGrantTypes # password, refresh_token, client_credentials
              • authorities # 具体权限
            • configure(AuthorizationServerEndpointsConfigurer) # 使用token的服务
              • authenticationManager # 密码认证
                • authenticate(Authentication)
              • userDetailService # 获取用户数据
                • loadUserByUsername(String)
              • authorizationCodeServices # 验证码
              • implicitGrantService
              • tokenGranter
              • tokenStore
                • InMemoryTokenStore
                • JdbcTokenStore
                • JwtTokenStore
            • configure(AuthorizationServerSecurityConfigurer) # 使用token服务的安全策略, 授权服务与资源服务分离时配置
        • 接口
          • Principal /users/current
        • 测试
          • insert into user(username, password) values(‘outrun’, ‘$2a$10$l7.7AJEHtXukwUZiKAyVSO6lHJOyHhPxHvi7MHawe8SjlOKkCVbAe’)
          • curl erp-auth-resource:a@localhost:9016/uaa/oauth/token -d grant_type=password -d username=outrun -d password=a
          • 浏览器
            • url: localhost:9016/uaa/oauth/token
            • header
              • ‘Authorization’: ‘Basic ’ + base64(‘erp-auth-resource:a’)
            • data
              • username: ‘outrun’
              • password: ‘123456’
              • grant_type: ‘password’
      • 资源服务
        • application.yml # client
        • 注解
          • @EnableResourceServer # 修饰ResourceServerConfigurerAdapter, 开启资源服务
            • 修饰AuthorizationServerConfigurerAdapter, 因为授权服务提供token获取和验证接口
          • @PreAuthorize(“hasAuthority(‘ROLE_ADMIN’)) # 修饰controller方法,验证权限
        • api
          • ResourceServerConfigurerAdapter # 资源服务配置
            • configure(HttpSecurity)
              • authorizeRequests # 请求放行
        • 测试
          • curl -d “username=outrun&password=a” “localhost:9017/user/registry”
          • insert into role values(1, ‘ROLE_USER’), (2, ‘ROLE_ADMIN’)
          • insert into ‘user_role’ values(user_id, 2)
          • curl erp-auth-resource:a@localhost:9016/uaa/oauth/token -d grant_type=password -d username=outrun -d password=a
          • curl -l -H “Authorization:Bearer 7df6669c-0c86-417b-827f-9a58297f57e5” -X GET “localhost:9017/hello”
      • 客户端
        • 注解
          • @EnableOAuth2Client # 修饰[Oauth2ClientConfig], 客户端
        • api
          • [Oauth2ClientConfig] # 客户端配置, 自定义类,名称任意
            • ClientCredentialsResourceDetails # bean, 资源信息
            • RequestInterceptor # bean, 保存请求上下文
            • OAuth2RestTemplate # bean, 用于向授权服务发送请求
        • clientdetails
        • oauth_access_token
        • oauth_approvals
        • oauth_client_details
        • oauth_client_token
        • oauth_code
        • oauth_refresh_token