因为是前后端分离的项目,所以最终方法的返回值都会放到请求体当中—>@RestController
所有文件与之前测试的相同
实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private Integer age;
private String address;
}
记得加注解,才会知道这个是个mapper接口
接口相应格式统一(另一项目的)
前端发送请求代码编写
出现了跨域问题
浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的HTTP请求,默认情况下是被禁止的。 同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。
4.5.2 CORS解决跨域 CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制,如果浏览器支持CORS、并且判断Origin通过的话,就会允许XMLHttpRequest发起跨域请求。
4.5.3 SpringBoot使用CORS解决跨域 1.使用@CrossOrigin可以在支持跨域的方法上或者是Controller上加上@CrossOrigin注解
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {
@Autowired
private UserServcie userServcie;
@RequestMapping("/findAll")
public ResponseResult findAll(){
//调用service查询数据 ,进行返回
List<User> users = userServcie.findAll();
return new ResponseResult(200,users);
}
}
@Configuration //表所示为配置类
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOriginPatterns("*")
// 是否允许cookie
.allowCredentials(true)
// 设置允许的请求方式
.allowedMethods("GET", "POST", "DELETE", "PUT")
// 设置允许的header属性
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}
比如:
运用debug
最终结果
data属性当中就是把我们后端响应的json字符串解析出来。
这样对前端来说判断方便很多
在前后端分离的场景中,很多时候会采用token的方案进行登录校验。
登录成功时,后端会根据一些用户信息生成一个token字符串返回给前端。
前端会存储这个token。以后前端发起请求时如果有token就会把token放在请求头中发送给后端。
后端接口就可以获取请求头中的token信息进行解析,如果解析不成功说明token超时了或者不是正确的token,相当于是未登录状态。
如果解析成功,说明前端是已经登录过的。
4.6.0.2 Token生成方案-JWT 本案例采用目前企业中运用比较多的JWT来生成token。
使用时先引入相关依赖
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
<version>0.9.0version>
dependency>
然后可以使用下面的工具类来生成和解析token
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
/**
* JWT工具类
*/
public class JwtUtil {
//有效期为
public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000 一个小时
//设置秘钥明文
public static final String JWT_KEY = "sangeng";
/**
* 创建token
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public static String createJWT(String id, String subject, Long ttlMillis) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
if(ttlMillis==null){
ttlMillis=JwtUtil.JWT_TTL;
}
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
SecretKey secretKey = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(id) //唯一的ID
.setSubject(subject) // 主题 可以是JSON数据
.setIssuer("sg") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
.setExpiration(expDate);// 设置过期时间
return builder.compact();
}
/**
* 生成加密后的秘钥 secretKey
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
* 解析
*
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
}
乱写就会抛出异常
数据准备
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
/*Data for the table `sys_user` */
insert into `sys_user`(`id`,`username`,`password`) values (1,'root','root'),(2,'sangeng','caotang');
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SystemUser {
private Integer id;
private String username;
private String password;
}
SystemUserController
import com.sangeng.domain.ResponseResult;
import com.sangeng.domain.SystemUser;
import com.sangeng.service.SystemUserService;
import com.sangeng.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/sys_user")
public class SystemUserController {
@Autowired
private SystemUserService userService;
@PostMapping("/login")
public ResponseResult login(@RequestBody SystemUser user) {
//校验用户名密码是否正确
SystemUser loginUser = userService.login(user);
Map<String, Object> map;
if (loginUser != null) {
//如果正确 生成token返回
map = new HashMap<>();
String token = JwtUtil.createJWT(UUID.randomUUID().toString(), String.valueOf(loginUser.getId()), null);
map.put("token", token);
} else {
//如果不正确 给出相应的提示
return new ResponseResult(300, "用户名或密码错误,请重新登录");
}
return new ResponseResult(200, "登录成功", map);
}
}
Service
public interface SystemUserService {
public SystemUser login(SystemUser user);
}
@Service
public class SystemUserServcieImpl implements SystemUserService {
@Autowired
private SystemUserMapper systemUserMapper;
@Override
public SystemUser login(SystemUser user) {
SystemUser loginUser = systemUserMapper.login(user);
return loginUser;
}
}
dao
@Mapper
@Repository
public interface UserMapper {
List<User> findAll();
}
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sangeng.mapper.SystemUserMapper">
<select id="login" resultType="com.sangeng.domain.SystemUser">
select * from sys_user where username = #{username} and password = #{password}
select>
mapper>
4.6.0.4 登录页面
<head>
<!-- Meta-->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="author" content="">
<title>BeAdmin - Bootstrap Admin Theme</title>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]><script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script><script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
<!-- Bootstrap CSS-->
<link rel="stylesheet" href="../app/css/bootstrap.css">
<!-- Vendor CSS-->
<link rel="stylesheet" href="../vendor/fontawesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../vendor/animo/animate+animo.css">
<!-- App CSS-->
<link rel="stylesheet" href="../app/css/app.css">
<link rel="stylesheet" href="../app/css/common.css">
<!-- Modernizr JS Script-->
<script src="../vendor/modernizr/modernizr.js" type="application/javascript"></script>
<!-- FastClick for mobiles-->
<script src="../vendor/fastclick/fastclick.js" type="application/javascript"></script>
</head>
<body>
<!-- START wrapper-->
<div class="row row-table page-wrapper" id="app">
<div class="col-lg-3 col-md-6 col-sm-8 col-xs-12 align-middle">
<!-- START panel-->
<div data-toggle="play-animation" data-play="fadeIn" data-offset="0" class="panel panel-dark panel-flat">
<div class="panel-heading text-center">
<a href="login.html#">
<img src="../app/img/logo.png" alt="Image" class="block-center img-rounded">
</a>
<p class="text-center mt-lg">
<strong>SIGN IN TO CONTINUE.</strong>
</p>
</div>
<div class="panel-body">
<form role="form" class="mb-lg">
<div class="text-right mb-sm"><a href="login.html#" class="text-muted">Need to Signup?</a>
</div>
<div class="form-group has-feedback">
<input id="exampleInputEmail1" v-model="user.username" type="email" placeholder="请输入用户名" class="form-control">
<span class="fa fa-envelope form-control-feedback text-muted"></span>
</div>
<div class="form-group has-feedback">
<input id="exampleInputPassword1" v-model="user.password" type="password" placeholder="请输入密码" class="form-control">
<span class="fa fa-lock form-control-feedback text-muted"></span>
</div>
<div class="clearfix">
<div class="checkbox c-checkbox pull-left mt0">
<label>
<input type="checkbox" value="">
<span class="fa fa-check"></span>Remember Me</label>
</div>
<div class="pull-right"><a href="login.html#" class="text-muted">Forgot your password?</a>
</div>
</div>
<button type="submit" class="btn btn-block btn-primary" @click="handleLogin()">登录</button>
</form>
</div>
</div>
<!-- END panel-->
</div>
</div>
<!-- END wrapper-->
<!-- START Scripts-->
<!-- Main vendor Scripts-->
<script src="../vendor/jquery/jquery.min.js"></script>
<script src="../vendor/bootstrap/js/bootstrap.min.js"></script>
<!-- Animo-->
<script src="../vendor/animo/animo.min.js"></script>
<!-- Custom script for pages-->
<script src="../app/js/pages.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var v = new Vue({
el:"#app",
data:{
user:{}
},
methods:{
handleLogin(){
//请求后台登录接口
axios.post("http://localhost/sys_user/login",this.user).then((res)=>{
// console.log(res);
//判断是否成功
if(res.data.code==200){
//登录成功
// alert("登录成功");
//存储token
localStorage.setItem("token",res.data.data.token);
//跳转页面到index.html
location.href = "/index.html";
}else{
//登录失败
alert(res.data.msg);
}
})
}
}
});
</script>
<!-- END Scripts-->
</body>
</html>
4.6.1 拦截器的概念(和MVC基本无异)
如果我们想在多个Handler方法执行之前或者之后都进行一些处理,甚至某些情况下需要拦截掉,不让Handler方法执行。那么可以使用SpringMVC为我们提供的拦截器。
详情见 https://space.bilibili.com/663528522 SpringMVC课程中拦截器相关章节。
4.6.1 使用步骤 ①创建类实现HandlerInterceptor接口public class LoginInterceptor implements HandlerInterceptor {
}
②实现方法
@Component //把类放到spring容器里面,底下为相应的业务逻辑
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的token
String token = request.getHeader("token");
//判断token是否为空,如果为空也代表未登录 提醒重新登录(401)
if(!StringUtils.hasText(token)){
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
//解析token看看是否成功
try {
Claims claims = JwtUtil.parseJWT(token);
String subject = claims.getSubject();
System.out.println(subject);
} catch (Exception e) {
e.printStackTrace();
//如果解析过程中没有出现异常说明是登录状态
//如果出现了异常,说明未登录,提醒重新登录(401)
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
return true;
}
}
③配置拦截器
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)//添加拦截器
.addPathPatterns("/**") //配置拦截路径
.excludePathPatterns("/sys_user/login");//配置排除路径
}
}
4.7 异常统一处理(整合MVC的)
①创建类加上@ControllerAdvice注解进行标识
@ControllerAdvice
public class MyControllerAdvice {
}
②定义异常处理方法
定义异常处理方法,使用 @ExceptionHandler 标识可以处理的异常。
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public ResponseResult handlerException(Exception e){
//获取异常信息,存放如ResponseResult的msg属性
String message = e.getMessage();
ResponseResult result = new ResponseResult(300,message);
//把ResponseResult作为返回值返回,要求到时候转换成json存入响应体中
return result;
}
}
4.8 获取web原生对象
我们之前在web阶段我们经常要使用到request对象,response,session对象等。我们也可以通过SpringMVC获取到这些对象。(不过在MVC中我们很少获取这些对象,因为有更简便的方式,避免了我们使用这些原生对象相对繁琐的API。)
我们只需要在方法上添加对应类型的参数即可,但是注意数据类型不要写错了,SpringMVC会把我们需要的对象传给我们的形参。
@RestController
public class TestController {
@RequestMapping("/getRequestAndResponse")
public ResponseResult getRequestAndResponse(HttpServletRequest request, HttpServletResponse response, HttpSession session){
System.out.println(request);
return new ResponseResult(200,"成功");
}
}
4.9 自定义参数解析
所有方法都用,这样就很麻烦。
如果我们想实现像获取请求体中的数据那样,在Handler方法的参数上增加一个@RepuestBody注解就可以获取到对应的数据的话。
可以使用HandlerMethodArgumentResolver来实现自定义的参数解析。
新建一个resolver包
①定义用来标识的注解
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUserId {
}
②创建类实现HandlerMethodArgumentResolver接口并重写其中的方法
注意加上@Component注解注入Spring容器
@Component
public class UserIdArgumentResolver implements HandlerMethodArgumentResolver {
//判断方法参数使用能使用当前的参数解析器进行解析
@Override
public boolean supportsParameter(MethodParameter parameter) {
//如果方法参数有加上CurrentUserId注解,就能把被我们的解析器解析
return parameter.hasParameterAnnotation(CurrentUserId.class);
}
//进行参数解析的方法,可以在方法中获取对应的数据,然后把数据作为返回值返回。方法的返回值就会赋值给对应的方法参数
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//获取请求头中的token
String token = webRequest.getHeader("token");
if(StringUtils.hasText(token)){
//解析token,获取userId
Claims claims = JwtUtil.parseJWT(token);
String userId = claims.getSubject();
//返回结果
return userId;
}
return null;
}
}
③配置参数解析器,因为HandlerMethodArgumentResolver 这种参数解析器属于MVC中的主键,我们要进行主键相关的配置。就像之前的
@Configuration
public class ArgumentResolverConfig implements WebMvcConfigurer {
@Autowired
private UserIdArgumentResolver userIdArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userIdArgumentResolver);
}
}
④测试
在需要获取UserId的方法中增加对应的方法参数然后使用@CurrentUserId进行标识即可获取到数据
@RestController
@RequestMapping("/user")
//@CrossOrigin
public class UserController {
@Autowired
private UserServcie userServcie;
@RequestMapping("/findAll")
public ResponseResult findAll(@CurrentUserId String userId) throws Exception {
System.out.println(userId);
//调用service查询数据 ,进行返回s
List<User> users = userServcie.findAll();
return new ResponseResult(200,users);
}
}
4.10 声明式事务
直接在需要事务控制的方法上加上对应的注解**@Transactional**
记得加在service层,因为是service层调用mapper对数据库 *** 作(业务层才涉及到事务)
@Service
public class UserServiceImpl implements UserServcie {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
@Transactional
public void insertUser() {
//添加2个用户到数据库
User user = new User(null,"sg666",15,"上海");
User user2 = new User(null,"sg777",16,"北京");
userMapper.insertUser(user);
System.out.println(1/0);
userMapper.insertUser(user2);
}
}
4.11 AOP(与spring一模一样,只是不用去配置)
AOP详细知识学习见:https://space.bilibili.com/663528522 中的Spring教程
在SpringBoot中默认是开启AOP功能的。如果不想开启AOP功能可以使用如下配置设置为false
spring:
aop:
auto: false
4.11.1 使用步骤
①添加依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
②自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokeLog {
}
③定义切面类
@Aspect //标识这是一个切面类
@Component
public class InvokeLogAspect {
//确定切点
@Pointcut("@annotation(com.sangeng.aop.InvokeLog)")
public void pt(){
}
@Around("pt()")
public Object printInvokeLog(ProceedingJoinPoint joinPoint){
//目标方法调用前
Object proceed = null;
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getMethod().getName();
System.out.println(methodName+"即将被调用");
try {
proceed = joinPoint.proceed();
//目标方法调用后
System.out.println(methodName+"被调用完了");
} catch (Throwable throwable) {
throwable.printStackTrace();
//目标方法出现异常了
System.out.println(methodName+"出现了异常");
}
return proceed;
}
}
④在需要正确的地方增加对应的注解
@Service
public class UserServiceImpl implements UserServcie {
@Autowired
private UserMapper userMapper;
@Override
@InvokeLog //需要被增强方法需要加上对应的注解
public List findAll() {
return userMapper.findAll();
}
}
4.11.2 切换动态代理
有的时候我们需要修改AOP的代理方式。
我们可以使用以下方式修改:
在配置文件中配置spring.aop.proxy-target-class为false这为使用jdk动态代理。该配置默认值为true,代表使用cglib动态代理。
@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = false)//修改代理方式
public class WebApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(WebApplication.class, args);
}
}
如果想生效还需要在配置文件中做如下配置
spring:
aop:
proxy-target-class: false #切换动态代理的方式
4.12 模板引擎相关-Thymeleaf
4.12.1 快速入门
4.12.1.1依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
4.12.1.2定义Controller
在controller中往域中存数据,并且跳转
@Controller
public class ThymeleafController {
@Autowired
private UserServcie userServcie;
@RequestMapping("/thymeleaf/users")
public String users(Model model){
//获取数据
List<User> users = userServcie.findAll();
//望域中存入数据
model.addAttribute("users",users);
model.addAttribute("msg","hello thymeleaf");
//页面跳转
return "table-standard";
}
}
4.12.1.3 htmL
在resources\templates下存放模板页面。
在html标签中加上 xmlns:th=“http://www.thymeleaf.org”
获取域中的name属性的值可以使用: ${name} 注意要在th开头的属性中使用
<html lang="en" class="no-ie" xmlns:th="http://www.thymeleaf.org">
.....
<div class="panel-heading" th:text="${msg}">Kitchen Sinkdiv>
如果需要引入静态资源,需要使用如下写法。
<link rel="stylesheet" th:href="@{/app/css/bootstrap.css}">
<link rel="stylesheet" th:href="@{/vendor/fontawesome/css/font-awesome.min.css}">
<link rel="stylesheet" th:href="@{/vendor/animo/animate+animo.css}">
<link rel="stylesheet" th:href="@{/vendor/csspinner/csspinner.min.css}">
<link rel="stylesheet" th:href="@{/app/css/app.css}">
<script th:src="@{/vendor/modernizr/modernizr.js}" type="application/javascript">script>
<script th:src="@{/vendor/fastclick/fastclick.js}" type="application/javascript">script>
遍历语法:遍历的语法 th:each=“自定义的元素变量名称 : ${集合变量名称}”
<tr th:each="user:${users}">
<td th:text="${user.id}">td>
<td th:text="${user.username}">td>
<td th:text="${user.age}">td>
<td th:text="${user.address}">td>
tr>
5.整合Redis
①依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
②配置Redis地址和端口号
spring:
redis:
host: 127.0.0.1 #redis服务器ip地址
port: 6379 #redis端口号
③注入RedisTemplate使用
@Autowired
private StringRedisTemplate redisTemplate;
@Test
public void testRedis(){
redisTemplate.opsForValue().set("name","三更");
}
6.环境切换
6.1 为什么要使用profile
在实际开发环境中,我们存在开发环境的配置,部署环境的配置,测试环境的配置等等,里面的配置信息很多时,例如:端口、上下文路径、数据库配置等等,若每次切换环境时,我们都需要进行修改这些配置信息时,会比较麻烦,profile的出现就是为了解决这个问题。它可以让我们针对不同的环境进行不同的配置,然后可以通过激活、指定参数等方式快速切换环境。
6.2 使用 6.2.1 创建profile配置文件 我们可以用application-xxx.yml的命名方式 创建配置文件,其中xxx可以根据自己的需求来定义。
例如
我们需要一个测试环境的配置文件,则可以命名为:application-test.yml
需要一个生产环境的配置文件,可以命名为:application-prod.yml
我们可以不同环境下不同的配置放到对应的profile文件中进行配置。然后把不同环境下都相同的配置放到application.yml文件中配置。
6.2.2 激活环境 我们可以再application.yml文件中使用spring.profiles.active属性来配置激活哪个环境。
也可以使用虚拟机参数来指定激活环境。例如 : -Dspring.profiles.active=test
也可以使用命令行参数来激活环境。例如: –spring.profiles.active =test
7.日志 开启日志
debug: true #开启日志
logging:
level:
com.sangeng: debug #设置日志级别
8.指标监控
我们在日常开发中需要对程序内部的运行情况进行监控, 比如:健康度、运行指标、日志信息、线程状况等等 。而SpringBoot的监控Actuator就可以帮我们解决这些问题。
8.1 使用①添加依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
②访问监控接口
http://localhost:81/actuator
③配置启用监控端点
management:
endpoints:
enabled-by-default: true #配置启用所有端点
web:
exposure:
include: "*" #web端暴露所有端点
8.2 常用端点
端点名称 | 描述 |
---|---|
beans | 显示应用程序中所有Spring Bean的完整列表。 |
health | 显示应用程序运行状况信息。 |
info | 显示应用程序信息。 |
loggers | 显示和修改应用程序中日志的配置。 |
metrics | 显示当前应用程序的“指标”信息。 |
mappings | 显示所有@RequestMapping 路径列表。 |
scheduledtasks | 显示应用程序中的计划任务。 |
①创建SpringBoot Admin Server应用
要求引入spring-boot-admin-starter-server依赖
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-serverartifactId>
dependency>
然后在启动类上加上@EnableAdminServer注解
②配置SpringBoot Admin client应用
在需要监控的应用中加上spring-boot-admin-starter-client依赖
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
<version>2.3.1version>
dependency>
然后配置SpringBoot Admin Server的地址
spring:
boot:
admin:
client:
url: http://localhost:8888 #配置 Admin Server的地址
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)