读书笔记 - Spring Boot实战

embedded/2025/3/12 1:03:42/

读书笔记 - Spring Boot实战

  • 第1章 入门
    • Spring Boot精要
      • 1. 自动配置
      • 2. 起步依赖
      • 3. 命令行界面
      • 4. Actuator
    • 使用Spring Initializr初始化Spring Boot项目
  • 第2章 运用SpringBoot
    • @SpringBootApplication
    • 配置应用程序属性
    • 指定基于功能的依赖
    • 覆盖起步依赖引入的传递依赖
    • 使用自动配置
  • 第3章 自定义配置
    • 覆盖Spring Boot自动配置
      • Spring Security例子
      • 创建自定义的安全配置
    • 掀开自动配置的神秘面纱
    • 通过属性文件外置配置
  • 第4章 测试
    • 集成测试自动配置
    • 测试Web应用程序
      • 模拟Spring MVC
      • 测试运行中的应用程序
      • 使用Selenium测试HTML页面
  • 第5章 Groovy与Spring Boot CLI
  • 第6章 在Spring Boot中使用Grails
    • 使用GORM进行数据持久化
    • GORM在Spring Boot里的另一个选择
  • 第7章 深入Actuator
    • SpringBoot中启用actuator
      • 引入监控插件
      • SecurityConfig关闭鉴权
      • yaml配置引入
      • 启用应用访问
      • 添加自定义度量信息
      • 创建自定义跟踪仓库
      • 自定义一个Amazon健康指示器
      • 保护Actuator端点
    • SpringBoot中启用actuator页面监控
      • 引入坐标
      • 启动类
      • yaml配置引入
      • 启用应用访问
    • Stagemonitor扩展集成
  • Spring Boot开发者工具
    • devtools
    • LiveReload

第1章 入门

Spring Boot精要

Spring Boot有四大神器,分别是auto-configuration、starters、cli、actuator,

Spring Boot将很多魔法带入了Spring应用程序的开发之中,其中最重要的是以下四个核心。
自动配置:针对很多Spring应用程序常见的应用功能,Spring Boot能自动提供相关配置。
起步依赖:告诉Spring Boot需要什么功能,它就能引入需要的库。
命令行界面:这是Spring Boot的可选特性,借此你只需写代码就能完成完整的应用程序,无需传统项目构建。
Actuator:让你能够深入运行中的Spring Boot应用程序,一探究竟。

1. 自动配置

在任何Spring应用程序的源代码里,你都会找到Java配置或XML配置(抑或两者皆有),它们为应用程序开启了特定的特性和功能。举个例子,,如果你写过用JDBC访问关系型数据库的应用程序。

这段非常简单的Bean声明创建了一个JdbcTemplate的实例,注入了一个DataSource依赖。

@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {  return new JdbcTemplate(dataSource);
}

还需要配置一个DataSource的Bean,这样才能满足依赖。假设你将配置一个嵌入式H2数据库作为DataSource Bean

public DataSource dataSource() {return new EmbeddedDatabaseBuilder()     .setType(EmbeddedDatabaseType.H2)     .addScripts('schema.sql', 'data.sql')     .build();
}

既然它如此常见,那为什么还要你去写呢?
Spring Boot会为这些常见配置场景进行自动配置。如果Spring Boot在应用程序的Classpath里发现H2数据库的库,那么它就自动配置一个嵌入式H2数据库。如果在Classpath里发现JdbcTemplate,那么它还会为你配置一个JdbcTemplate的Bean。你无需操心那些Bean的配置,Spring Boot会做好准备,随时都能将其注入到你的Bean里。

2. 起步依赖

向项目中添加依赖是件富有挑战的事。你需要什么库?它的Group和Artifact是什么?你需要哪个版本?哪个版本不会和项目中的其他依赖发生冲突?

Spring Boot通过起步依赖为项目的依赖管理提供帮助。起步依赖其实就是特殊的Maven依赖和Gradle依赖,利用了传递依赖解析,把常用库聚合在一起,组成了几个为特定功能而定制的依赖,如下。

org.springframework:spring-core
org.springframework:spring-web
org.springframework:spring-webmvc
com.fasterxml.jackson.core:jackson-databind
org.hibernate:hibernate-validator
org.apache.tomcat.embed:tomcat-embed-core
org.apache.tomcat.embed:tomcat-embed-el
org.apache.tomcat.embed:tomcat-embed-logging-juli

应用是个Web应用程序,所以加入了Web起步依赖。与之类似,如果应用程序要用到JPA持久化,那么就可以加入jpa起步依赖。如果需要安全功能,那就加入security起步依赖。简而言之,你不再需要考虑支持某种功能要用什么库了,引入相关起步依赖就行。

org.springframework.boot:spring-boot-starter-web

3. 命令行界面

除了自动配置和起步依赖,Spring Boot还提供了一种很有意思的新方法,可以快速开发Spring应用程序。

Spring Boot CLI利用了起步依赖和自动配置,让你专注于代码本身。
不仅如此,你是否注意到代码清单1-1里没有import?
CLI如何知道RequestMapping和RestController来自哪个包呢?
说到这个问题,那些类最终又是怎么跑到Classpath里的呢?
说得简单一点,CLI能检测到你使用了哪些类,它知道要向Classpath中添加哪些起步依赖才能让它运转起来。一旦那些依赖出现在Classpath中,一系列自动配置就会接踵而来,确保启用DispatcherServlet和Spring MVC,这样控制器就能响应HTTP请求了。

4. Actuator

Actuator则要提供在运行时检视应用程序内部情况的能力。安装了Actuator就能窥探应用程序的内部情况了,包括如下细节:

  • Spring应用程序上下文里配置的Bean
  • Spring Boot的自动配置做的决策
  • 应用程序取到的环境变量、系统属性、配置属性和命令行参数
  • 应用程序里线程的当前状态
  • 应用程序最近处理过的HTTP请求的追踪情况
  • 各种和内存用量、垃圾回收、Web请求以及数据源用量相关的指标
    Actuator通过Web端点和shell界面向外界提供信息。如果要借助shell界面,你可以打开SSH(Secure Shell),登入运行中的应用程序,发送指令查看它的情况。

使用Spring Initializr初始化Spring Boot项目

  1. 使用Spring Initializr的Web界面,最直接的办法就是用浏览器打开http://start.spring.io,你应该能看到一个表单。
  2. 在Spring Tool Suite里创建Spring Boot项目
  3. 在IntelliJ IDEA里创建Spring Boot项目
  4. 在Spring Boot CLI里使用Initializr

第2章 运用SpringBoot

@SpringBootApplication

@SpringBootApplication开启了Spring的组件扫描和Spring Boot的自动配置功能。实际上,@SpringBootApplication将三个有用的注解组合在了一起。
Spring的@Configuration:标明该类使用Spring基于Java的配置。
Spring的@ComponentScan:启用组件扫描,这样你写的Web控制器类和其他组件才能被自动发现并注册为Spring应用程序上下文里的Bean。Spring MVC控制器使用@Controller进行注解,这样组件扫描才能找到它。
Spring Boot的@EnableAutoConfiguration:这个不起眼的小注解也可以称为@Abracadabra,就是这一行配置开启了Spring Boot自动配置的魔力,让你不用再写成篇的配置了。

配置应用程序属性

application.properties文件可以很方便地帮你细粒度地调整Spring Boot的自动配置。

server.port=8000

指定基于功能的依赖

Spring Boot通过提供众多起步依赖降低项目依赖的复杂度。

dependencies {compile "org.springframework.boot:spring-boot-starter-web"compile "org.springframework.boot:spring-boot-starter-thymeleaf"compile "org.springframework.boot:spring-boot-starter-data-jpa"compile "com.h2database:h2"testCompile("org.springframework.boot:spring-boot-starter-test")
}

通过传递依赖,添加这四个依赖就等价于加了一大把独立的库。这些传递依赖涵盖了SpringMVC、Spring Data JPA、Thymeleaf等内容,它们声明的依赖也会被传递依赖进来。

不知道自己所用依赖的版本,你多少会有些不安。
在Gradle里,dependencies任务会显示一个依赖树,其中包含了项目所用的每一个库以及它们的版本:

$ gradle dependencies

在Maven里使用dependency插件的tree目标也能获得相似的依赖树。

$ mvn dependency:tree

覆盖起步依赖引入的传递依赖

以Spring Boot的Web起步依赖为例,它传递依赖了Jackson JSON库。如果你正在构建一个生产或消费JSON资源表述的REST服务,那它会很有用。但是,要构建传统的面向人类用户的Web应用程序,你可能用不上Jackson。虽然把它加进来也不会有什么坏处,但排除掉它的传递依赖,可以为你的项目瘦身。

compile("org.springframework.boot:spring-boot-starter-web") {exclude group: 'com.fasterxml.jackson.core'
}

另一方面,也许项目需要Jackson,但你需要用另一个版本的Jackson来进行构建,而不是Web起步依赖里的那个。假设Web起步依赖引用了Jackson 2.3.4,但你需要使用2.4.3

compile("com.fasterxml.jackson.core:jackson-databind:2.4.3")

使用自动配置

每当应用程序启动的时候,Spring Boot的自动配置都要做将近200个这样的决定,涵盖安全、集成、持久化、Web开发等诸多方面。
Spring的JdbcTemplate是不是在Classpath里?如果是,并且有DataSource的Bean,则自动配置一个JdbcTemplate的Bean。
Thymeleaf是不是在Classpath里?如果是,则配置Thymeleaf的模板解析器、视图解析器以及模板引擎。
Spring Security是不是在Classpath里?如果是,则进行一个非常基本的Web安全设置。

第3章 自定义配置

覆盖Spring Boot自动配置

大多数情况下,自动配置的Bean刚好能满足你的需要,不需要去覆盖它们。但某些情况下,Spring Boot在自动配置时还不能很好地进行推断。

Spring Security例子

当你在应用程序里添加安全特性时,自动配置做得还不够好。安全配置并不是放之四海而皆准的,围绕应用程序安全有很多决策要做,Spring Boot不能替你做决定。想知道如何用显式的配置来覆盖自动配置,我们先从为阅读列表应用程序添加Spring Security入手。

Spring Boot自动配置让应用程序的安全工作变得易如反掌,你要做的只是添加Security起步依赖。
compile(“org.springframework.boot:spring-boot-starter-security”)
这样就搞定了!重新构建应用程序后运行即可,现在这就是一个安全的Web应用程序了!Security起步依赖在应用程序的Classpath里添加了Spring Secuirty(和其他一些东西)。Classpath里有Spring Security后,自动配置就能介入其中创建一个基本的Spring Security配置。

默认的配置不是我们想要的效果,让我们看看如何写出Spring Secuirty配置,覆盖自动配置的安全设置吧。

创建自定义的安全配置

覆盖自动配置很简单,就当自动配置不存在,直接显式地写一段配置。这段显式配置的形式不限,Spring支持的XML和Groovy形式配置都可以。在编写显式配置时,我们会专注于Java形式的配置。在Spring Security的场景下,这意味着写一个扩展了ebSecurityConfigurerAdapter
的配置类。
覆盖自动配置的显式安全配置如下:

package com.cmcc.framework.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
/*** spring security配置** @author ruoyi*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 自定义用户认证逻辑*/@Autowiredprivate UserDetailsService userDetailsService;/*** 认证失败处理类*/@Autowiredprivate AuthenticationEntryPointImpl unauthorizedHandler;/*** 退出处理类*/@Autowiredprivate LogoutSuccessHandlerImpl logoutSuccessHandler;/*** token认证过滤器*/@Autowiredprivate JwtAuthenticationTokenFilter authenticationTokenFilter;/*** 跨域过滤器*/@Autowiredprivate CorsFilter corsFilter;/*** 允许匿名访问的地址*/@Autowiredprivate PermitAllUrlProperties permitAllUrl;/*** 解决 无法直接注入 AuthenticationManager** @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** anyRequest          |   匹配所有请求路径* access              |   SpringEl表达式结果为true时可以访问* anonymous           |   匿名可以访问* denyAll             |   用户不能访问* fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)* hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问* hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问* hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问* hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问* hasRole             |   如果有参数,参数表示角色,则其角色可以访问* permitAll           |   用户可以任意访问* rememberMe          |   允许通过remember-me登录的用户访问* authenticated       |   用户登录后可访问*/@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {// 注解标记允许匿名访问的urlExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());httpSecurity// CSRF禁用,因为不使用session.csrf().disable()// 禁用HTTP响应标头.headers().cacheControl().disable().and()// 认证失败处理类.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()// 基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 过滤请求.authorizeRequests()// 对于登录login 注册register 验证码captchaImage 允许匿名访问.antMatchers("/login",// 静态资源,可匿名访问.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll().antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs","/v2/*", "/druid/**").permitAll()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated().and().headers().frameOptions().disable();// 添加Logout filterhttpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);// 添加JWT filterhttpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 添加CORS filterhttpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);}/*** 强散列哈希加密实现*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder() {return new BCryptPasswordEncoder();}/*** 身份认证接口*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}
}

SecurityConfig是个非常基础的Spring Security配置,尽管如此,它还是完成了不少安全定制工作。通过这个自定义的安全配置类,我们让Spring Boot跳过了安全自动配置,转而使用我们的安全配置。

掀开自动配置的神秘面纱

想要覆盖Spring Boot的自动配置,你所要做的仅仅是编写一个显式的配置。Spring Boot会发现你的配置,随后降低自动配置的优先级,以你的配置为准。想弄明白这是如何实现的,让我们揭开Spring Boot自动配置的神秘面纱,看看它是如何运作的,以及它是怎么允许自己被覆盖的。

Spring Boot自动配置自带了很多配置类,每一个都能运用在你的应用程序里。它们都使用了Spring 4.0的条件化配置,可以在运行时判断这个配置是该被运用,还是该被忽略。

Spring Boot的DataSourceAutoConfiguration中定义的JdbcTemplate Bean就是一个非常简单的例子,演示了@ConditionalOnMissingBean如何工作:

@Bean
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {return new JdbcTemplate(this.dataSource);
}

关于Spring Security,自动配置会考虑几个配置类。在这里讨论每个配置类的细节是不切实际的,但覆盖Spring Boot自动配置的安全配置时,最重要的一个类是SpringBootWebSecurityConfiguration。以下是其中的一个代码片段:

@Configuration
@EnableConfigurationProperties
@ConditionalOnClass({ EnableWebSecurity.class })
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
@ConditionalOnWebApplication
public class SpringBootWebSecurityConfiguration {...
}

看到@ConditionalOnClass注解后,你就应该知道Classpath里必须要有@EnableWebSecurity注解。

@ConditionalOnMissingBean注解才是我们的安全配置类代替SpringBootWebSecurityConfiguration的关键所在。

@ConditionalOnMissingBean注解要求当下没有WebSecurityConfiguration类型的Bean。虽然表面上我们并没有这么一个Bean,但通过在SecurityConfig上添加@EnableWebSecurity注解,我们实际上间接创建了一个WebSecurityConfiguration Bean。所以在自动配置时,这个Bean就已经存在了,@ConditionalOnMissingBean条件不成立,SpringBootWebSecurityConfiguration提供的配置就被跳过了。

通过属性文件外置配置

在处理应用安全时,你当然会希望完全掌控所有配置。不过,为了微调一些细节,比如改改端口号和日志级别。Spring Boot自动配置的Bean提供了300多个用于微调的属性。
#如果你想禁用这个Banner
spring.main.show-banner=false
#还可以将属性设置为环境变量。举例来说,如果你用的是bash或者zsh,可以用export命令:
$ export spring_main_show_banner=false

实际上,Spring Boot应用程序有多种设置途径。Spring Boot能从多种属性源获得属性,包括如下几处。
(1)命令行参数
(2)java:comp/env里的JNDI属性
(3)JVM系统属性
(4)操作系统环境变量
(5)随机生成的带random.*前缀的属性(在设置其他属性时,可以引用它们,比如${random.long})
(6)应用程序以外的application.properties或者appliaction.yml文件
(7)打包在应用程序内的application.properties或者appliaction.yml文件
(8)通过@PropertySource标注的属性源
(9)默认属性
这个列表按照优先级排序,也就是说,任何在高优先级属性源里设置的属性都会覆盖低优先级的相同属性。例如,命令行参数会覆盖其他属性源里的属性。

例如,命令行参数会覆盖其他属性源里的属性。application.properties和application.yml文件能放在以下四个位置。
(1)外置,在相对于应用程序运行目录的/config子目录里。
(2)外置,在应用程序运行的目录里。
(3)内置,在config包内。
(4)内置,在Classpath根目录。
同样,这个列表按照优先级排序。也就是说,/config子目录里的application.properties会覆盖应用程序Classpath里的application.properties中的相同属性。
此外,如果你在同一优先级位置同时有application.properties和application.yml,那么application.yml里的属性会覆盖application.properties里的属性。

第4章 测试

集成测试自动配置

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=AddressBookConfiguration.class)
public class AddressServiceTests {...
}

@SpringApplicationConfiguration加载Spring应用程序上下文的方式同SpringApplication
相同,处理方式和生产应用程序中的情况相同。这包括加载外部属性和Spring Boot日志。

测试Web应用程序

@RequestMapping(method=RequestMethod.POST)
public String addToReadingList(Book book) {book.setReader(reader);readingListRepository.save(book);return "redirect:/readingList";
}

save方法的测试,Spring Boot开发者有两个可选的方案能实现这类测试。
Spring Mock MVC:能在一个近似真实的模拟Servlet容器里测试控制器,而不用实际启动应用服务器。
Web集成测试:在嵌入式Servlet容器(比如Tomcat或Jetty)里启动应用程序,在真正的应用服务器里执行测试。

模拟Spring MVC

Spring Framework就有了一套非常实用的Web应用程序测试工具,能模拟Spring MVC,不需要真实的Servlet容器也能对控制器发送HTTP请求。Spring的Mock MVC框架模拟了Spring MVC的很多功能。它几乎和运行在Servlet容器里的应用程序一样,尽管实际情况并非如此。

要在测试里设置Mock MVC,可以使用MockMvcBuilders,该类提供了两个静态方法。
standaloneSetup():构建一个Mock MVC,提供一个或多个手工创建并配置的控制器。
webAppContextSetup():使用Spring应用程序上下文来构建Mock MVC,该上下文里可以包含一个或多个配置好的控制器。
前者同单元测试更加接近,你可能只想让它专注于单一控制器的测试,而后者让Spring加载控制器及其依赖,以便进行完整的集成测试。

测试运行中的应用程序

说到测试Web应用程序,我们还没接触实质内容。在真实的服务器里启动应用程序,用真实的Web浏览器访问它,这样比使用模拟的测试引擎更能展现应用程序在用户端的行为。

Spring Boot找到了解决方案。它支持将Tomcat或Jetty这样的嵌入式Servlet容器作为运行中的应用程序的一部分,可以运用相同的机制,在测试过程中用嵌入式Servlet容器来启动应用程序。Spring Boot的@WebIntegrationTest注解就是这么做的。在测试类上添加@WebIntegrationTest注解,可以声明你不仅希望Spring Boot为测试创建应用程序上下文,还要启动一个嵌入式的Servlet容器。一旦应用程序运行在嵌入式容器里,你就可以发起真实的HTTP请求,断言结果了。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=ReadingListApplication.class)
@WebIntegrationTest            ←---在服务器里运行测试
public class SimpleWebTest {***
}

使用Selenium测试HTML页面

RestTemplate对于简单的请求而言使用方便,是测试REST端点的理想工具。但是,就算它能对返回HTML页面的URL发起请求,也不方便对页面内容或者页面上执行的操作进行断言。

对于HTML应用程序测试,有一个更好的选择——Selenium(www.seleniumhq.org),它的功能远不止提交请求和获取结果。Selenium的测试是自动的,而且可以重复运行。
首先需要把Selenium作为测试依赖添加到项目里:

testCompile("org.seleniumhq.selenium:selenium-java:2.45.0")

这个测试里最值得注意的是,@WebIntegrationTest可以为我们启动应用程序和服务器,这样Selenium才可以用Web浏览器执行测试。但真正有趣的是你可以使用IDE的测试功能来运行测试,运行几次都行,无需依赖构建过程中的某些插件启动服务器。

要是你觉得使用Selenium进行测试很实用,可以阅读Yujun Liang和Alex Collins的SeleniumWebDriver in Practice(http://manning.com/liang/),该书更深入地讨论了Selenium测试的细节。

第5章 Groovy与Spring Boot CLI

Groovy本身是种优雅的语言。用Groovy编写Book领域类相当简单。如果在阅读列表项目的根目录里创建一个新的文件,名为Book.groovy,那么在这里编写如下Groovy类。

class Book {Long idString readerString isbnString titleString authorString description
}

如你所见,Groovy类与它的Java类相比,大小完全不在一个量级。这里没有setter和getter方法,没有public和private修饰符,也没有分号。Java中常见的代码噪声不复存在,剩下的内容都在描述书的基本信息。

第6章 在Spring Boot中使用Grails

使用GORM进行数据持久化

Grails里最让人着迷的恐怕就是GORM了。GORM将数据库相关工作简化到和声明要持久化的实体一样容易。

package readinglist
import grails.persistence.*@Entity          ←---这是一个GORM实体
class Book {Reader readerString isbnString titleString authorString description
}

就和Book的Java版本一样,这个类里有很多描述图书的属性。但又与Java版本不一样,这里没有分号、public或private修饰符、setter和getter方法或其他Java中常见的代码噪声。

要在Spring Boot项目里使用GORM,必须在项目里添加GORM依赖。

compile("org.grails:gorm-hibernate4-spring-boot:1.1.0.RELEASE")

GORM在Spring Boot里的另一个选择

如果你想用MongoDB,那你会对Spring Boot里的MongoDB GORM支持很感兴趣。

compile("org.grails:gorm-mongodb-spring-boot:1.1.0.RELEASE")

GORM的工作原理要求实体类必须用Groovy来编写。

Groovy的ReadingListController
@RequestMapping(method=RequestMethod.POST)def addToReadingList(Reader reader, Book book) {Book.withTransaction {book.setReader(reader)book.save()      ←---保存一本书}"redirect:/"}

Grails项目也提供GSP的自动配置。如果你想在Spring Boot应用程序里使用GSP,必须向项目里添加Spring Boot的GSP库:

compile("org.grails:grails-gsp-spring-boot:1.0.0")

第7章 深入Actuator

端点可以分为三大类:配置端点、度量端点和其他端点。让我们分别了解一下这些端点,从提供应用程序配置信息的端点看起。
在这里插入图片描述

SpringBoot中启用actuator

引入监控插件

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

SecurityConfig关闭鉴权

.antMatchers("/actuator/*").permitAll()

yaml配置引入

management:endpoints:web:exposure:include: "*"exclude: info

启用应用访问

http://192.168.0.34:8298/cmcc-tenant/actuator

添加自定义度量信息

从/metrics端点获得运行中应用程序的内部度量信息,包括内存、垃圾回收和线程信息。这些都是非常有用且信息量很大的度量值,但你可能还想定义自己的度量,用来捕获应用程序中的特定信息。

比方说,我们想要知道用户往阅读列表里保存了多少次图书,自动配置允许Actuator创建CounterService的实例,并将其注册为Spring的应用程序上下文中的Bean。CounterService
这个接口里定义了三个方法,分别用来增加、减少或重置特定名称的度量值,代码如下:

package org.springframework.boot.actuate.metrics;
public interface CounterService {void increment(String metricName);void decrement(String metricName);void reset(String metricName);
}

创建自定义跟踪仓库

默认情况下,/trace端点报告的跟踪信息都存储在内存仓库里,100个条目封顶。一旦仓库满了,就开始移除老的条目,给新的条目腾出空间。在开发阶段这没什么问题,但在生产环境中,大流量会造成跟踪信息还没来得及看就被丢弃。

为了避免这个问题,你可以声明自己的InMemoryTraceRepository
Bean,将它的容量调整至100以上。如下配置类可以将容量调整至1000个条目:

package readinglist;import org.springframework.boot.actuate.trace.InMemoryTraceRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ActuatorConfig {@Beanpublic InMemoryTraceRepository traceRepository() {InMemoryTraceRepository traceRepo = new InMemoryTraceRepository();traceRepo.setCapacity(1000);return traceRepo;}
}

除了上述方法,我们还可以将那些跟踪条目存储在其他地方——既不消耗内存,又能长久保存的地方。只需实现Spring Boot的TraceRepository
接口即可:

package org.springframework.boot.actuate.trace;import java.util.List;
import java.util.Map;public interface TraceRepository {List<Trace> findAll();void add(Map<String, Object> traceInfo);
}

如你所见,TraceRepository只要求我们实现两个方法:一个方法查找所有存储的Trace对象,另一个保存了一个Trace,包含跟踪信息的Map对象。
插入自定义健康指示器
Actuator自带了很多健康指示器,能满足常见需求,比如报告应用程序使用的数据库和消息代理的健康情况。但如果你的应用程序需要和一些没有健康指示器的系统交互,那该怎么办呢?

自定义一个Amazon健康指示器

package readinglist;import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;@Component
public class AmazonHealth implements HealthIndicator {@Overridepublic Health health() {try {RestTemplate rest = new RestTemplate();// 向 Amazon 发送请求rest.getForObject("http://www.amazon.com", String.class);return Health.up().build();} catch (Exception e) {// 报告 DOWN 状态
//            return Health.down().build();//如果有很多附加信息,可以多次调用withDetail()方法,每次设置一个要放入健康记录的附加字段。return Health.down().withDetail("reason", e.getMessage()).build();}}
}

保护Actuator端点

要保护Actuator的端点,我们需要对SecurityConfig.java的configure()方法做些修改。

保护/shutdown端点,要访问/shutdown端点,必须用一个带ADMIN权限的用户来做身份验证。

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").access("hasRole('READER')").antMatchers("/shutdown").access("hasRole('ADMIN')")// 要求有 ADMIN 权限.antMatchers("/**").permitAll().and().formLogin().loginPage("/login").failureUrl("/login?error=true");
}

添加一个内存里的admin用户,新加的内存身份验证中,用户名定义为admin,密码为s3cr3t,同时被授予ADMIN和READER权限。

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(new UserDetailsService() {// Reader 身份验证@Overridepublic 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("s3cr3t").roles("ADMIN", "READER");// Admin 身份验证
}

SpringBoot中启用actuator页面监控

引入坐标

<!-- Spring Boot Admin Server 依赖 -->
<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.6.6</version>
</dependency>
<!-- Spring Boot Admin Client 依赖 -->
<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-client</artifactId><version>2.6.6</version>
</dependency>

启动类

@SpringBootApplication
@EnableAdminServer

yaml配置引入

spring:boot:admin:client:url: "http://192.168.0.34:${server.port}"

启用应用访问

启动失败

2025-03-08 10:38:43.690 [] [] [registrationTask1] WARN  d.c.b.a.c.r.ApplicationRegistrator - [register,91] - Failed to register application as Application(name=spring-boot-application, 
managementUrl=http://DESKTOP-082N99E.mshome.net:8298/cmcc-tenant/actuator, 
healthUrl=http://DESKTOP-082N99E.mshome.net:8298/cmcc-tenant/actuator/health, 
serviceUrl=http://DESKTOP-082N99E.mshome.net:8298/cmcc-tenant) at spring-boot-admin ([http://localhost:8298/admin/instances]): 404 : "<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1></body></html>". Further attempts are logged on DEBUG level

Stagemonitor扩展集成


https://blog.csdn.net/qq_16046891/article/details/109206608

Spring Boot开发者工具

自动重启:当Classpath里的文件发生变化时,自动重启运行中的应用程序。
LiveReload支持:对资源的修改自动触发浏览器刷新。
远程开发:远程部署时支持自动重启和LiveReload。
默认的开发时属性值:为一些属性提供有意义的默认开发时属性值。

devtools

compile "org.springframework.boot:spring-boot-devtools"

应用程序的代码则会加载到一个单独的重启类加载器里。检测到变更时,只有重启类加载器重启。有些Classpath里的资源变更后不需要重启应用程序。像Thymeleaf这样的视图模板可以直接编辑,不用重启应用程序。在/static或/public里的静态资源也不用重启应用程序,所以SpringBoot开发者工具会在重启时排除掉如下目录:/META-INF/resources、/resources、/static、/public和/templates。

可以设置spring.devtools.restart.exclude属性来覆盖默认的重启排除目录。例如,你只排除/static和/templates目录,可以像这样设置spring.devtools.restart.exclude:

spring:devtools:restart:exclude: /static/**,/templates/**

还可以设置一个触发文件,必须修改这个文件才能触发重启。例如,在修改名为.trigger的文件前你都不希望执行重启,那么你只需像这样设置spring.devtools.restart.trigger-file属性:

spring:devtools:restart:trigger-file: .trigger

LiveReload

在Web应用程序开发过程中,最常见的步骤大致如下。
(1)修改要呈现的内容(比如图片、样式表、模板)。
(2)点击浏览器里的刷新按钮,查看修改的结果。
(3)回到第1步。
虽然这并不难,但如果能不点刷新就直接看到修改结果,那岂不是更好?
Spring Boot的开发者工具集成了LiveReload(http://livereload.com
),可以消除刷新的步骤。激活开发者工具后,Spring Boot会启动一个内嵌的LiveReload服务器,在资源文件变化时会触发浏览器刷新。你要做的就是在浏览器里安装LiveReload插件。
如果想要禁用内嵌的LiveReload服务器,可以将spring.devtools.livereload.enabled
设置为false:

spring:devtools:livereload:enabled: false

http://www.ppmy.cn/embedded/171889.html

相关文章

基于Asp.net的高校迎新管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

C#程序结构及基本组成说明

C# 程序的结构主要由以下几个部分组成,以下是对其结构的详细说明和示例: 1. 基本组成部分 命名空间 (Namespace) 用于组织代码,避免命名冲突。通过 using 引入其他命名空间。 using System; // 引入 System 命名空间类 (Class) C# 是面向对象的语言,所有代码必须定义在类或…

速算迷你世界脚本UI

--[[ --数学速算主界面 local UI"6996144362677448610" local v"6996144362677448610_" --自定义玩家数据界面 --显示界面分类 -- --称号积分幼儿园0学前班50小学生200初中生500高中生1000大学生2000研究生5000博士生10000教授50000 local A {["主屏幕…

Tomcat 新手入门指南:从零开始掌握安装与配置

Tomcat 新手入门指南&#xff1a;从零开始掌握安装与配置 一、Tomcat 是什么&#xff1f; Apache Tomcat 是一个开源的 轻量级 Web 应用服务器&#xff0c;专为运行 Java Servlet 和 JSP 设计。它是初学 Java Web 开发的必备工具&#xff0c;也是企业级应用的常见选择。 核心…

开源!速度100Kb/s的有线和无线双模ESP32S3芯片的DAP-Link调试器

开源&#xff01;速度100Kb/s的有线和无线双模ESP32S3芯片的DAP-Link调试器 目录 开源&#xff01;速度100Kb/s的有线和无线双模ESP32S3芯片的DAP-Link调试器本项目未经授权&#xff0c;禁止商用&#xff01;本项目未经授权&#xff0c;禁止商用&#xff01;本项目未经授权&…

C++ Primer Plus第十二章课后习题总结

1. 对于下面的类声明&#xff1a; class Cow {char name[20];char * hobby;double weight;public:Cow();Cow(const char * nm, const char * ho, double wt);Cow(const Cow c&);~Cow();Cow & operator(const Cow & c);void ShowCow() const; // display all cow d…

rust语言match模式匹配涉及转移所有权Error Case

struct S{data:String, }//注意&#xff1a;因为String默认是移动语义&#xff0c;从而决定结构体S也是移动语义&#xff0c;可采用(1)或(2)两种方法解决编译错误&#xff1b;关键思路&#xff1a;放弃获取结构体S的字段data的所有权&#xff0c;改为借用。fn process(s_ref:&a…

文件上传漏洞测试

upload-labs16关 源码: function isImage($filename){//需要开启php_exif模块$image_type exif_imagetype($filename);switch ($image_type) {case IMAGETYPE_GIF:return "gif";break;case IMAGETYPE_JPEG:return "jpg";break;case IMAGETYPE_PNG:retur…