《SpringCloud超级入门》Spring Boot项目搭建步骤(超详细)《六

本文介绍了如何在SpringBoot项目中管理多环境配置,使用hotdeploy快速部署,利用actuator进行健康检查和自定义端点,以及统一异常处理和异步执行的实践。
摘要由CSDN通过智能技术生成

读取配置的方法代码如下。

@RestController

public class HelloController {

@Autowired

private MyConfig myConfig;

@GetMapping(“/hello”)

public String hello() {

return myConfig.getName();

}

}

定义配置 application.properties 的方法如下:

net.biancheng.name=zhangsan

profiles 多环境配置


在平时的开发中,项目会被部署到测试环境、生产环境,但是每个环境的数据库地址等配置信息都是不一样的。通过 profile 来激活不同环境下的配置文件就能解决配置信息不一样的问题。在 Spring Boot 中可以通过 spring.profiles.active=dev 来激活不同环境下的配置。

可以定义多个配置文件,每个配置文件对应一个环境,格式为 application-环境.properties,如表 1 所示。

在开发环境中,可以通过修改 application.properties 中的 spring.profiles.active 的值来激活对应环境的配置,在部署的时候可以通过 java–jar xxx.jar–spring.profiles.active=dev 来指定使用对应的配置。

热部署


开发过程中经常会改动代码,此时若想看下效果,就不得不停掉项目然后重启。

对于 Spring Boot 项目来说,启动时间是非常快的,在微服务的架构下,每个服务只关注自己的业务,代码量也非常小,这个启动时间是可以容忍的。

通过 spring-boot-devtools 就可以实现热部署。

只需要添加 spring-boot-devtools 的依赖即可实现热部署功能,代码如下所示。

org.springframework.boot

spring-boot-devtools

actuator 监控


Spring Boot 提供了一个用于监控和管理自身应用信息的模块,它就是 spring-boot-starter-actuator。该模块使用起来非常简单,只需要加入依赖即可,代码如下。

org.springframework.boot

spring-boot-starter-actuator

启动项目我们会发现在控制台输出的内容中增加了 所示的信息。

比如,我们访问 /actuator/health 可以得到下面的信息:

{

“status”: “UP”

}

Spring Boot启动控制台输出

Spring Boot启动控制台输出

Actuator端点信息

UP 表示当前应用处于健康状态,如果是 DOWN 就表示当前应用不健康。增加下面的配置可以让一些健康信息的详情也显示出来:

management.endpoint.health.show-details=ALWAYS

再次访问 /actuator/health,就可以得到健康状态的详细信息数据:

{

“status”: “UP”,

“diskSpace”: {

“status”: “UP”,

“total”: 491270434816,

“free”: 383870214144,

“threshold”: 10485760

}

}

大部分端点默认都不暴露出来,我们可以手动配置需要暴露的端点。如果需要暴露多个端点,可以用逗号分隔,如下所示:

management.endpoints.web.exposure.include=configprops,beans

如果想全部端点都暴露的话直接配置成下面的方式:

management.endpoints.web.exposure.include=*

后面我们会介绍如何使用 Spring Boot Admin在页面上更加直观地展示这些信息,目前都是 Json 格式的数据,不方便查看。

自定义 actuator 端点


我们需要自定义一些规则来判断应用的状态是否健康,可以采用自定义端点的方式来满足多样性的需求。如果我们只是需要对应用的健康状态增加一些其他维度的数据,可以通过继承 AbstractHealthIndicator 来实现自己的业务逻辑。代码如下。

@Component

public class UserHealthIndicator extends AbstractHealthIndicator {

@Override

protected void doHealthCheck(Builder builder) throws Exception {

builder.up().withDetail(“status”, true);

// builder.down().withDetail(“status”, false);

}

}

通过 up 方法指定应用的状态为健康,down 方法指定应用的状态为不健康。withDetail 方法用于添加一些详细信息。访问 /actuator/health,可以得到我们自定义的健康状态的详细信息:

{

“status”: “UP”,

“details”: {

“user”: {

“status”: “UP”,

“details”: {

“status”: true

}

},

“diskSpace”: {

“status”: “UP”,

“details”: {

“total”:

249795969024,

“free”: 7575375872,

“threshold”: 10485760

}

}

}

}

上面我们是在框架自带的 health 端点中进行扩展,还有一种需求是完全开发一个全新的端点,比如查看当前登录的用户信息的端点。自定义全新的端点很简单,通过 @Endpoint 注解就可以实现。代码如下所示。

@Component

@Endpoint(id = “user”)

public class UserEndpoint {

@ReadOperation

public List<Map<String, Object>> health() {

List<Map<String, Object>> list = new ArrayList<>();

Map<String, Object> map = new HashMap<>();

map.put(“userId”, 1001);

map.put(“userName”, “zhangsan”);

list.add(map);

return list;

}

}

访问 /actuator/user 可以看到返回的用户信息如下:

[

{

“userName”: “zhangsan”,

“userId”: 1001

}

]

统一异常处理


对于接口的定义,我们通常会有一个固定的格式

{

“status”: true,

“code”: 200,

“message”: null,

“data”: [

{

“id”: “101”,

“name”: “jack”

},

{

“id”: “102”,

“name”: “jason”

}

]

}

如果调用方在请求我们的 API 时把接口地址写错了,就会得到一个 404 错误:

{

“timestamp”: 1492063521109,

“status”: 404,

“error”: “Not Found”,

“message”: “No message available”,

“path”: “/rest11/auth”

}

后端服务会告诉我们哪个地址没找到,其实也挺友好。但是因为我们上面自定义的数据格式跟下面的不一致,所以当用户拿到这个返回的时候是无法识别的,其中最明显的是 status 字段。

我们自定义的是 boolean 类型,用来表示请求是否成功,这里返回的就是 Http 的状态码,所以我们需要在发生这种系统错误时也能返回我们自定义的那种格式,那就要定义一个异常处理类(代码如下所示),通过这个类既可以返回统一的格式,也可以统一记录异常日志。

@ControllerAdvice

public class GlobalExceptionHandler {

private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

@ExceptionHandler(value = Exception.class)

@ResponseBody

public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {

logger.error(“”, e);

ResponseData r = new ResponseData();

r.setMessage(e.getMessage());

if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {

r.setCode(404);

} else {

r.setCode(500);

}

r.setData(null);

r.setStatus(false);

return r;

}

}

ResponseData 是我们返回格式的实体类,其发生错误时也会被捕获到,然后封装好返回格式并返回给调用方。在 Spring Boot 的配置文件中加上如下代码所示配置。

出现错误时, 直接抛出异常

spring.mvc.throw-exception-if-no-handler-found=true

不要为我们工程中的资源文件建立映射

spring.resources.add-mappings=false

当我们调用一个不存在的接口时,返回的错误信息就是我们自定义的那种格式:

{

“status”: false, “code”: 404,

“message”: “No handler found for GET /rest11/auth”, “data”: null

}

最后贴上 ResponseData 的定义,代码如下。

public class ResponseData {

private Boolean status = true;

private int code = 200;

private String message;

private Object data;

// get set …

}

异步执行


异步调用就是不用等待结果的返回就执行后面的逻辑;同步调用则需要等待结果再执行后面的逻辑。

通常我们使用异步操作时都会创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下所示。

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(() -> {

try {

// 业务逻辑

} catch (Exception e) {

e.printStackTrace();

} finally {

}

});

这种方式尽管使用了 Java 的 Lambda,但看起来没那么优雅。在 Spring 中有一种更简单的方式来执行异步操作,只需要一个 @Async 注解即可,代码如下所示。

@Async

public void saveLog() {

System.err.println(Thread.currentThread().getName());

}

我们可以直接在 Controller 中调用这个业务方法,它就是异步执行的,会在默认的线程池中去执行。需要注意的是,一定要在外部的类中去调用这个方法,如果在本类调用则不起作用,比如 this.saveLog()。最后在启动类上开启异步任务的执行,添加 @EnableAsync 即可。

@Configuration

@ConfigurationProperties(prefix = “spring.task.pool”)

public class TaskThreadPoolConfig {

// 核心线程数

private int corePoolSize = 5;

// 最大线程数

private int maxPoolSize = 50;

// 线程池维护线程所允许的空闲时间

private int keepAliveSeconds = 60;

// 队列长度

private int queueCapacity = 10000;

// 线程名称前缀

private String threadNamePrefix = “FSH-AsyncTask-”;

// get set …

}

然后我们重新定义线程池的配置,代码如下所示。

@Configuration

public class AsyncTaskExecutePool implements AsyncConfigurer {

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

“FSH-AsyncTask-”;

// get set …

}

然后我们重新定义线程池的配置,代码如下所示。

@Configuration

public class AsyncTaskExecutePool implements AsyncConfigurer {

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-NjMTrShL-1710847568447)]
[外链图片转存中…(img-Xapb2JBq-1710847568447)]
[外链图片转存中…(img-Rv1GUdwr-1710847568448)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-PuordaOC-1710847568448)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值