网站首页 > 技术文章 正文
1.打开IDEA,右上角选择File→New→Project 选择Spring Initializr
2.点击Next,这里我直接下一步
完了上述操作之后,在 pom.xml 中可以看到如下依赖。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
启动类,代码如下所示。
package com.kaibin.springbootdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
启动类使用了 @SpringBootApplication 注解,这个注解表示该类是一个 Spring Boot 应用。直接运行 App 类即可启动,启动成功后在控制台输出信息,默认端口是 8080,如图 2 所示。
我们之所以能够通过一个 Main 方法启动一个 Web 服务,是因为 Sprig Boot 中内嵌了 Tomcat,然后通过内嵌的 Tomcat 来提供服务。当然,我们也可以使用别的容器来替换 Tomcat,比如 Undertow 或 Jetty。
编写第一个 REST 接口
本节将创建一个控制器,编写第一个 REST 接口,访问地址使用 /hello,代码如下所示。
package com.kaibin.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
@RestController 是 @Controller 和 @ResponseBody 的组合注解,可以直接返回 Json 格式数据。
@GetMapping 其实就是 @RequestMapping(method=RequestMethod.GET),通过访问 http://localhost:8080/hello 可以看到输出的结果“hello”,如图 3 所示。
读取配置文件
在以前的项目中我们主要在 XML 文件中进行框架配置,业务的相关配置会放在属性文件中,然后通过一个属性读取的工具类来读取配置信息。
在 Spring Boot 中我们不再需要使用这种方式去读取数据了。Spring Boot 中的配置通常放在 application.properties 中,读取配置信息非常方便,总共分为 3 种方式。
1)Environment
可以通过 Environment 的 getProperty 方法来获取想要的配置信息,代码如下所示。
package com.kaibin.springbootdemo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
// 注入对象
@Autowired
private Environment env;
@GetMapping("/hello")
public String hello() {
// 读取配置
String port = env.getProperty("server.port");
return port;
}
}
2)@Value
可以注入具体的配置信息,代码如下所示。
@RestController
public class HelloController {
// 注入配置
@Value("${server.port}")
private String port;
@GetMapping("/hello")
public String hello() {
return port;
}
}
3)自定义配置类
prefix 定义配置的前缀,代码如下所示。
@ConfigurationProperties(prefix = "com.kaibin")
@Component
public class MyConfig {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
读取配置的方法代码如下所示。
@RestController
public class HelloController {
@Autowired
private MyConfig myConfig;
@GetMapping("/hello")
public String hello() {
return myConfig.getName();
}
}
定义配置 application.properties 的方法如下:
com.kaibin.name=kb
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 启动很快,但是我们还是要自己去重启。能不能做到有改动,它就会悄无声息地自己把改动的地方重新加载一遍?答案是肯定的,通过 spring-boot-devtools 就可以实现。
只需要添加 spring-boot-devtools 的依赖即可实现热部署功能,代码如下所示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
actuator 监控
Spring Boot 提供了一个用于监控和管理自身应用信息的模块,它就是 spring-boot-starter-actuator。该模块使用起来非常简单,只需要加入依赖即可,代码如下所示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
我们访问 /actuator/health 可以得到下面的信息:
{
"status": "UP"
}
UP 表示当前应用处于健康状态,如果是 DOWN 就表示当前应用不健康。增加下面的配置可以让一些健康信息的详情也显示出来:
management.endpoint.health.show-details=ALWAYS
再次访问 /actuator/health,就可以得到健康状态的详细信息:
{
"status": "UP",
"components": {
"diskSpace": {
"status": "UP",
"details": {
"total": 314572795904,
"free": 273426538496,
"threshold": 10485760,
"exists": true
}
},
"ping": {
"status": "UP"
}
}
}
大部分端点默认都不暴露出来,我们可以手动配置需要暴露的端点。如果需要暴露多个端点,可以用逗号分隔,如下所示:
management.endpoints.web.exposure.include=configprops,beans
如果想全部端点都暴露的话直接配置成下面的方式:
management.endpoints.web.exposure.include=*
关于这些监控的信息不再赘述,大家可以自行了解。后面我们会介绍如何使用 Spring Boot Admin 在页面上更加直观地展示这些信息,目前都是 Json 格式的数据,不方便查看。
统一异常处理
对于接口的定义,我们通常会有一个固定的格式,比如:
{
"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 的状态码,所以我们需要在发生这种系统错误时也能返回我们自定义的那种格式,那就要定义一个异常处理类(代码如下所示),通过这个类既可以返回统一的格式,也可以统一记录异常日志。
package com.kaibin.springbootdemo.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@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 /hello1",
"data": null
}
最后贴上 ResponseData 的定义,代码如下所示。
package com.kaibin.springbootdemo.exception;
public class ResponseData {
private Boolean status = true;
private int code = 200;
private String message;
private Object data;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
猜你喜欢
- 2024-10-09 用IDEA把SpringBoot项目打成jar发布项目
- 2024-10-09 SpringBoot 01 环境搭建入门(简单springboot项目搭建)
- 2024-10-09 IDEA中创建Springboot父子工程(idea创建父子项目)
- 2024-10-09 16:实现SpringBoot单个、多个文件的上传
- 2024-10-09 手把手教你用Spring-Boot搭建项目
- 2024-10-09 Spring Boot入门-快速搭建web项目
- 2024-10-09 使用IDEA创建gradle的spring boot项目并提交到DS916+的git server上
- 2024-10-09 Springboot工程建立(springboot工程搭建步骤)
- 2024-10-09 SpringBoot进阶3:项目搭建方法与项目结构分析
- 2024-10-09 SpringBoot+Mybatis多模块(module)项目搭建教程
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- js判断是否空对象 (63)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- phprequire_once (61)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)