Spring Boot的一些笔记

时间:2022-08-14 20:34:33
官方文档
https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready-endpoints

1、Spring问题
    Spring 某些配置要显示配置
    Spring 项目依赖管理麻烦


    Spring Boot精要
    a、自动配置:对Sping应用程序常见功能能自动提供相关配置

    b、起步依赖:告诉Spring Boot需要什么功能,就能引入需要的库

    c、命令行界面

    d、Actuator:深入运行中的Spring Boot应用程序


    Spring Boot不是什么    
    a、Spring boot不是应用服务器,虽然他可以把web编程可执行的JAE文件,不用部署到Servlet容器中,内嵌了一个Servlet容器(Tomcat、Jetty或Undertow)

    b、没有实现如JPA或JMS,但自动装配了某个JPA实现的Bean以支持JPA

    c、没有引入任何形式的代码生成,利用了Spring 4的条件配置特性以及Mave和Gradle提供的传递依赖解析,以此实现Spring应用程序上下文里的自动配置

    d、SpringBoot就是Spring,只是设置了一些配置


2、Application类作用
    配置
    启动引导

    //开启组件扫描和自动配置
    @SpringBootApplication
    public class HotdeployApplication{
        //这个main方法可以把程序挡车一个可执行的JAR文件
        public static void main(String[] args) {
            //负责启动引导应用程序
            SpringApplication.run(HotdeployApplication.class, args);
        }
    }

    a、@SpringBootApplication:三个注解组合
       Spring 的 @Configuration:该类使用Spring基于Java的配置
       Spring 的 @ComponentScan:启用组件扫描,web控制器类和其他组件才能被自动发现并注册为Spring的上下文中的bean
       Spring 的 @EnableAutoConfiguration:开启Spring Boot的自动配置

    如果要配置Spring boot以外的Spring配置,写到一个@Configuration标注的类里(能自动扫描到)

3、Application.yml配置文件作用
    如 sever.port=8000
    细粒度调整Spring Boot的自动装配,还可以指定应用程序代码所需配置项

4、Spring-boot-autoconfigure的jar文件包含很多配置类

5、深入Actuator
    Spring Boot Acturator在应用程序里提供了众多的Web端点,通过他了解应用程序运行时的内部状况和配置信息

    加入依赖spring-boot-starter-actuator
    https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready-endpoints
 Spring Boot 2.0 暴露端点方法management.endpoints.web.expose="*"
    
查看配置明细    
5.1、Beans装配报告:描述应用程序上下文所有bean及其关系
    
    http://localhost:8080/actuator/beans
    得到json数据
    一个个bean:BeanID、aliases别名、scope作用域、type类型、resource资源文件、dependency依赖

5.2、autoconfig详解自动配置:记录哪些自动配置条件通过了,哪些没通过,注意2.0后改为了conditions
    
    http://localhost:8080/actuator/conditions
    positiveMatches成功条件、negativeMatches失败条件等等、condition条件

5.3、env查看配置属性:获取全部环境属性(环境变量、JVM属性、命令行参数、Application文件属性),注意key、password、secret为名的属性值为*
    
    http://localhost:8080/actuator/env
    systemProperties JVM系统属性

    获取单个属性值:http://localhost:8080/actuator/env/amazon.associate_id

5.4、mappings生成端点到控制器的映射:描述全部的URL路径,以及它们和控制器(包括Actuator端点)的映射关系
    
    http://localhost:8080/actuator/mappings


    "{[/girls],methods=[GET]}"的根路径请求、bean处理请求的bean、methoh请求映射到该方法
    
运行时度量
5.4、metrics查看应用程序的度量值:比如内存用量和http请求计数
    
    http://localhost:8080/actuator/metrics
    注意2.0没有直接显示值,要通过这个给的字符串继续拼接查值
    http://localhost:8080/actuator/metrics/jvm.buffer.memory.used

5.5、trace追踪web请求:提供基本的http请求跟踪信息(时间戳、http头等)

    http://localhost:8080/actuator/trace
    timestamp请求处理时间、headers请求头内容、path请求路径

    显示最近100个请求信息,后面创建一个自定义跟踪库实现便于持久化跟踪

5.6、dump生成当前线程活动的快照:注意2.0有两个heapdump和threaddump,导出堆和线程活动

    http://localhost:8080/actuator/threaddump

5.7、health监控应用程序健康活动

    http://localhost:8080/actuator/threaddump
    status属性显示应用程序正在运行中,如果经过身份验证(登录)会提供更多信息
    如可用磁盘空间已经应用程序正在使用的数据库状态

    后面自定义配置健康指示器

5.8、showdown关闭应用程序:注意默认关闭该端点

    post请求

    开启:endpoints.shutdown.enabled.true,2.0不是这个心累看文档  
    endpoint:
            shutdown:
                  enabled: true
    http://localhost:8080/actuator/shutdown
    不知道为什么未知错误

5.9、info获取应用信息

    http://localhost:8080/actuator/info
    默认是空信息,在Application中加info信息
    info:
          contactEmail: 155316@qq.com

    后面看其他配置与扩展Actuator的方式

...2.0还增加了其他的端点

loggers
Shows and modifies the configuration of loggers in the application.
flyway
Shows any Flyway database migrations that have been applied.
liquibase
Shows any Liquibase database migrations that have been applied.
scheduledtasks
Displays the scheduled tasks in your application.
sessions
Allows retrieval and deletion of user sessions from a Spring Session-backed session store. Not available when using Spring Session’s support for reactive web applications.
logfile
Returns the contents of the logfile (if logging.file or logging.path properties have been set). Supports the use of the HTTP Range header to retrieve part of the log file’s content.

6、连接Actuator的远程shell:深入运行中应用程序内部的方式

    Spring Boot 集成了CRaSH,一种1能嵌入任意java应用程序的shell,还进行了扩展
    添加spring-boot-starter-remote-shell依赖
    启动项目看到写入日志的一行密码password    2.0没找到不知道为什么

// 后面都是2.0以下版本使用方式
7、定制Actuator
    重命名端点、启用和禁用端点、自定义度量信息、创建自定义查看存储跟踪数据、自定义健康指示器

7.1、修改端点ID
    endpoints.shutdown.id=kill

7.2、启用和禁用端点
    endpoints.metrics.enabled=false    2.0可以用management.endpoints.web.exclude=env排除

7.3、添加自定义度量信息:比如想知道访问某个方法多少次
    
    a、时间戳:System.currentTime-Millis()获取

    b、Actuator创建CounterService实例注册为上下文Bean,CounterService接口3个方法
    increment(String metricName);    增加度量值
    decrement(String metricName);    减少度量值
    reset(String metricName);    重置度量值

    c、Acturator会配置一个GaugeService类型的Bean
    submit(String metricName,double value);    保存值到某个度量值

        无需实现,Spring Boot提供了两者实现,只要把他们实例注入所需Bean,调用方法就行了

        并没有用,注入失败,没有实现,2.0也找不到这两货
    
    d、实现PublicMetrics接口,提供自己需要的度量信息,2.0找不到
    @Component
    public class ApplicationContextMetrics implements PublicMetrics {
        private ApplicationContext context;
            @Autowired
            public ApplicationContextMetrics(ApplicationContext context){
                this.context = context;
            }

            @Override
            public Collection<Metric<?>> metrics() {
                   List<Metric<?>> metrics = new ArrayList<Metric<?>>();
                    //记录启动时间
                    metrics.add(new Metric<Long>("spring.context.startup-date",context.getStartupDate()));
                   //记录Bean定义数量
                metrics.add(new Metric<Integer>("spring.beans.definitions",context.getBeanDefinitionCount()));
                //记录Bean数量
                metrics.add(new Metric<Integer>("spring.beans",context.getBeanNamesForType(Object.class).length));
                //记录控制器类个数
                metrics.add(new Metric<Integer>("spring.controllers",context.getBeanNamesForAnnotation(Controller.class).length));
                        return metrics;
            }
    }
    再调用http://localhost:8080/metrics,可以看到上面信息,Controller个数要加上Spring Boot提供的BasicErrorController

7.4、创建自定义跟踪仓库:/trace端点只能存100个条目

    声明自己的InMemoryTraceRepository Bean,将其容量调整到100以上,2.0有这个
    @Configuration
    public class ActuatorConfig {
        @Bean
            public InMemoryTraceRepository traceRepository(){
                InMemoryTraceRepository traceRepo = new InMemoryTraceRepository();
                traceRepo.setCapacity(1000);
                return  traceRepo;
            }
    }

    将跟踪目录存到其他地方,实现Spring Boot的TraceRepository接口,2.0有这个上
    findAll()方法和add(Map<String,Object> traceInfo)

    例子中用到了mongoDB,暂时不写了

7.5、插入自定义健康指示器:例如报告某某功能是否能使用

    /**
     * 自定义一个健康指示器
     */
    @Component
    public class ActuatorHealth implements HealthIndicator
    {
            @Override
            public Health health() {
                try {
                        RestTemplate rest = new RestTemplate();
                        //发请求
                        rest.getForObject("http://localhost:8080/health",String.class);
                        //成功状态up
                        return Health.up().build();
                }catch (Exception e){
                        //失败报告DOWN状态
                        return Health.down().build();
                }
            }
    }

    2.0在控制台打印出来,错了直接显示DOWN
    2.0以下加了访问直接卡死什么鬼

7.6、保护端点:比如shutdown端点,能访问他们只能是那些经过授权的客户端

    protected void configure(
            AuthenticationManagerBuilder auth ) throws Exception{

        auth
                .userDetailsService(new UserDetailsService() {
                    @Override
                    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                            UserDetails user = readerRepository.findOne(username);
                            if(user != null){
                                return user;
                            }
                            throw new UsernameNotFoundException("User '" + username + "' not found");
                        }

                })
                .and()
                .inMemoryAuthentication()
                    .withUser("admin").password("123").roles("ADMIN","READER"); //admon身份验证,除了admin权限用户谁都无法访问shutdown

    }

    或者通过management。context-path=/mgmt 所有端点都与/mgmt路径相关
    有了公共的前缀,赋予权限是能借助这个公共前缀



8、其他
    
8.1、用随机端口启动服务器
        设置server.port=0
        @Value("${local.server.port}")为当前端口值

        测试用@WebIntegrationTest(randomPort=true)
    
8.2、自定义配置
    原理:用到了Spring4.0的条件化配置@Conditional(*.class),该条件满足才配置
    a、显示引入依赖配置
    b、Application.yml文件配置具体值:如具体数据库的配置

8.3、Security保护应用程序
    引入spring-boot-starter-security依赖

    访问时就要输入用户名密码了否则报401,但是密码是随机生成的,自定义安全设置吧
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ReaderRepository readerRepository;
    protected void configure(HttpSecurity http)throws Exception{
        http
                .authorizeRequests()
                    .antMatchers("/hello").access("hasRole('READER')")   //要求登录者要有该权限
                    .antMatchers("/**").permitAll()            //其他访问不要权限

                .and()

                .formLogin()
                    .loginPage("/login")                //设置登陆表单路径,没权限进入这登录
                    .failureForwardUrl("/login?error=true");
    }

    protected void configure(
            AuthenticationManagerBuilder auth ) throws Exception{

        auth
                .userDetailsService(new UserDetailsService() {
                    @Override
                    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                            return  readerRepository.findOne(username);
                        }

                });

    }

}
其中readerRepository是JPA访问数据库

8.4、Spring Boot 用 Logback记录日志,替换为log4j
    首先排除默认起步依赖
        <dependency> <artifactId>spring-boot-starter-logging</artifactId>
                 <exclusions><exclusion><artifactId>spring0boot-starter0logging</artifactId>...
    然加入log4j依赖:spring-boot-start-log4j
    最后细节设置在Application.yml中设置,如同数据源配置

9、部署Spring Boot应用程序

    a、IDE运行

    b、Maven的Spring-boot:run命令
    
    c、Maven生成JAR文件,用java -jar运行

    d、Spring Boot CLI在命令行中运行Groovy脚本

    e、Spring Boot CLI生成JAR文件,命令行运行

    开发环境:以上都适合在
    生产环境下部署:除了IDE运行不可行,可以考虑的jar和Spring Boot CLI可以考虑

    部署产物        产生方式                目标环境
    Groovvy源码        手写                    Cloud Foundry及容器部署如Docker
    可执行JAR        Maven、Gradle或Spring Boot CLI        云环境,及以上
    WAR            Maven或Gradle                Java应用服务器或云环境,如Cloud Foundry
    
    如Tomcat考虑WAR,其他考虑JAR等
    
9.1、部署到应用服务器:Spring Boot通过内嵌Tomcat提供服务,与传统程序部署到Tomcat相反

    Maven
        jar:mvn clean install -DskipTests 构建jar包,命令行(java -jar *.jar)运行Spring Boot
            注意要设置主类
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.2-beta-5</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.imooc.demo.GirlApplication</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        war:
            a、设置pom.xml中packaging为war
            b、注意要引入依赖      
                  <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->  
                        <dependency>  
                            <groupId>javax.servlet</groupId>  
                            <artifactId>javax.servlet-api</artifactId>  
                            <version>3.1.0</version>  
                            <scope>provided</scope>  
                        </dependency>  
            c、同时启动类继承SpringBootServletInitializer并复写SpringApplicationBuilder()方法
                public class GirlApplication extends SpringBootServletInitializer{
                    @Override
                    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
                        //指定Spring配置
                        return builder.sources(GirlApplication.class);
                    }
                }

            d、mvn clean install -DskipTests 构建war包,命令行(java -jar *.war)运行Spring Boot
            e、或者把war放到Tomcat webapps中,启动tomcat即可,注意访问路径要加上文件名了。tomcat打不开要设置java和jrehome
        
            war包好处,同一个部署产物两个部署方式