SpringBoot错误处理流程深入详解

目录
  • 一、错误处理
  • 二、底层相关组件
  • 三、异常处理流程
  • 四、定制错误处理逻辑
    • 1、自定义错误页面
    • 2、使用注解或者默认的异常处理
    • 3、自定义异常处理解析器

一、错误处理

默认情况下,Spring Boot提供/error处理所有错误的映射

对于机器客户端(例如PostMan),它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息(如果设置了拦截器,需要在请求头中塞入Cookie相关参数)

对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据

另外,templates下面error文件夹中的4xx,5xx页面会被自动解析

二、底层相关组件

那么Spring Boot是怎么实现上述的错误页相关功能的呢?

我们又要来找一下相关源码进行分析了

首先我们先了解一个概念:@Bean配置的类的默认id是方法的名称,但是我们可以通过value或者name给这个bean取别名,两者不可同时使用

我们进入ErrorMvcAutoConfiguration,看这个类名应该是和错误处理的自动配置有关,我们看下这个类做了什么

向容器中注册类型为DefaultErrorAttributes,id为errorAttributes的bean(管理错误信息,如果要自定义错误页面打印的字段,就自定义它),这个类实现了ErrorAttributes, HandlerExceptionResolver(异常处理解析器接口), Ordered三个接口

@Bean
@ConditionalOnMissingBean(
    value = {ErrorAttributes.class},
    search = SearchStrategy.CURRENT
)
public DefaultErrorAttributes errorAttributes() {
    return new DefaultErrorAttributes();
}

点进去后发现,这个类是和我们响应页面中的message、error等字段有关

向容器中注册一个id为basicErrorController的控制器bean(管理错误相应逻辑,不想返回json或者错误视图,就自定义它)

@Bean
@ConditionalOnMissingBean(
    value = {ErrorController.class},
    search = SearchStrategy.CURRENT
)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvider<ErrorViewResolver> errorViewResolvers) {
    return new BasicErrorController(errorAttributes, this.serverProperties.getError(), (List)errorViewResolvers.orderedStream().collect(Collectors.toList()));
}

这个控制器就和前面我们返回json或者错误视图有关

声明类型为DefaultErrorViewResolver,id为conventionErrorViewResolver的bean(管理错误视图跳转路径,如果要改变跳转路径,就自定义它)

@Configuration(
   proxyBeanMethods = false
)
@EnableConfigurationProperties({WebProperties.class, WebMvcProperties.class})
static class DefaultErrorViewResolverConfiguration {
   private final ApplicationContext applicationContext;
   private final Resources resources;
   DefaultErrorViewResolverConfiguration(ApplicationContext applicationContext, WebProperties webProperties) {
       this.applicationContext = applicationContext;
       this.resources = webProperties.getResources();
   }
   @Bean
   @ConditionalOnBean({DispatcherServlet.class})
   @ConditionalOnMissingBean({ErrorViewResolver.class})
   DefaultErrorViewResolver conventionErrorViewResolver() {
       return new DefaultErrorViewResolver(this.applicationContext, this.resources);
   }
}

这个类中,解释了为什么前面会根据不同的状态码转向不同的错误页

声明一个静态内部类WhitelabelErrorViewConfiguration,它与错误视图配置相关,这个类中声明了一个id为error的视图对象提供给basicErrorController中使用,还定义了视图解析器BeanNameViewResolver ,它会根据返回的视图名作为组件的id去容器中找View对象

@Configuration(
   proxyBeanMethods = false
)
@ConditionalOnProperty(
   prefix = "server.error.whitelabel",
   name = {"enabled"},
   matchIfMissing = true
)
@Conditional({ErrorMvcAutoConfiguration.ErrorTemplateMissingCondition.class})
protected static class WhitelabelErrorViewConfiguration {
   private final ErrorMvcAutoConfiguration.StaticView defaultErrorView = new ErrorMvcAutoConfiguration.StaticView();
   protected WhitelabelErrorViewConfiguration() {
   }
   @Bean(
       name = {"error"}
   )
   @ConditionalOnMissingBean(
       name = {"error"}
   )
   public View defaultErrorView() {
       return this.defaultErrorView;
   }
   @Bean
   @ConditionalOnMissingBean
   public BeanNameViewResolver beanNameViewResolver() {
       BeanNameViewResolver resolver = new BeanNameViewResolver();
       resolver.setOrder(2147483637);
       return resolver;
   }
}

另外还声明了一个静态内部类StaticView,这里面涉及错误视图的渲染等相关操作

private static class StaticView implements View {
   private static final MediaType TEXT_HTML_UTF8;
   private static final Log logger;
   private StaticView() {
   }
   public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
       if (response.isCommitted()) {
           String message = this.getMessage(model);
           logger.error(message);
       } else {
           response.setContentType(TEXT_HTML_UTF8.toString());
           StringBuilder builder = new StringBuilder();
           Object timestamp = model.get("timestamp");
           Object message = model.get("message");
           Object trace = model.get("trace");
           if (response.getContentType() == null) {
               response.setContentType(this.getContentType());
           }
           ...

三、异常处理流程

为了了解Spring Boot的异常处理流程,我们写一个demo进行debug

首先写一个会发生算术运算异常的接口/test_error

/**
 * 测试报错信息
 * @return 跳转错误页面
 */
@GetMapping(value = "/test_error")
public String testError() {
    int a = 1/0;
    return String.valueOf(a);
}

然后放置一个错误页面5xx.html于templates下的error文件夹中

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
  <meta name="description" content="">
  <meta name="author" content="ThemeBucket">
  <link rel="shortcut icon" href="#" rel="external nofollow"  rel="external nofollow"  type="image/png">
  <title>500 Page</title>
  <link href="css/style.css" rel="external nofollow"  rel="stylesheet">
  <link href="css/style-responsive.css" rel="external nofollow"  rel="stylesheet">
  <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
  <!--[if lt IE 9]>
  <script src="js/html5shiv.js"></script>
  <script src="js/respond.min.js"></script>
  <![endif]-->
</head>
<body class="error-page">
<section>
    <div class="container ">
        <section class="error-wrapper text-center">
            <h1><img alt="" src="images/500-error.png"></h1>
            <h2>OOOPS!!!</h2>
            <h3 th:text="${message}">Something went wrong.</h3>
            <p class="nrml-txt" th:text="${trace}">Why not try refreshing you page? Or you can <a href="#" rel="external nofollow"  rel="external nofollow" >contact our support</a> if the problem persists.</p>
            <a class="back-btn" href="index.html" rel="external nofollow"  th:text="${status}"> Back To Home</a>
        </section>
    </div>
</section>
<!-- Placed js at the end of the document so the pages load faster -->
<script src="js/jquery-1.10.2.min.js"></script>
<script src="js/jquery-migrate-1.2.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/modernizr.min.js"></script>
<!--common scripts for all pages-->
<!--<script src="js/scripts.js"></script>-->
</body>
</html>

然后我们开启debug模式,发送请求

首先,我们的断点还是来到DispatcherServlet类下的doDispatch()方法

经过mv = ha.handle(processedRequest, response, mappedHandler.getHandler());调用目标方法之后,他会返回相关错误信息,并将其塞入dispatchException这个对象

然后调用this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);处理调度结果

然后他会在processDispatchResult()中经过判断是否存在异常,异常不为空,调用processHandlerException()方法,这里它会遍历系统中所有的异常处理解析器,哪个解析器返回结果不为null,就结束循环

在调用DefaultErrorAttributes时,它会将错误中的信息放入request请求域中(我们后面模板引擎页面解析会用到)

遍历完所有解析器,我们发现他们都不能返回一个不为空的ModelAndView对象,于是它会继续抛出异常

当系统发现没有任何人能处理这个异常时,底层就会发送 /error 请求,它就会被我们上面介绍的BasicErrorController下的errorHtml()方法处理

这个方法会通过ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);去遍历系统中所有的错误视图解析器,如果调用解析器的resolveErrorView()方法返回结果不为空就结束循环

系统中只默认注册了一个错误视图解析器,也就是我们上面介绍的DefaultErrorViewResolver,跟随debug断点我们得知,这个解析器会把error+响应状态码作为错误页的地址,最终返回给我们的视图地址为error/5xx.html

四、定制错误处理逻辑

1、自定义错误页面

error下的4xx.html和5xx.html,根据我们上面了解的DefaultErrorViewResolver类可以,它的resolveErrorView()方法在进行错误页解析时,如果有精确的错误状态码页面就匹配精确,没有就找 4xx.html,如果都没有就转到系统默认的错误页

2、使用注解或者默认的异常处理

@ControllerAdvice+@ExceptionHandler处理全局异常,我们结合一个demo来了解一下用法

首先我们创建一个类用来处理全局异常

package com.decade.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
@Slf4j
public class MyExceptionHandler {
   // 指定该方法处理某些指定异常,@ExceptionHandler的value可以是数组,这里我们指定该方法处理数学运算异常和空指针异常
   @ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
   public String handleArithmeticException(Exception exception) {
       log.error("异常信息为:{}", exception);
       // 打印完错误信息后,返回登录页
       return "login";
   }
}

我们还是使用上面的会发生算术运算异常的接口/test_error进行测试

请求接口后发现,页面跳转到登录页了

为什么没有再走到5xx.html呢?

因为@ControllerAdvice+@ExceptionHandler的底层是ExceptionHandlerExceptionResolver来处理的

这样在进入DispatcherServlet类下的processHandlerException()方法时,就会调用ExceptionHandlerExceptionResolver这个异常处理解析器,从而跳转到我们自己创建的异常处理类进行异常处理,然后返回不为null的ModelAndView对象给它,终止遍历,不会再发送/error请求

@ResponseStatus+自定义异常

首先我们自定义一个异常类

package com.decade.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
// code对应错误码,reason对应message
@ResponseStatus(code = HttpStatus.METHOD_NOT_ALLOWED, reason = "自定义异常")
public class CustomException extends RuntimeException {
   public CustomException() {
   }
   public CustomException(String message) {
       super(message);
   }
}

然后写一个接口去抛出自定义异常

/**
* 测试报错信息
* @return 跳转错误页面
*/
@GetMapping(value = "/test_responseStatus")
public String testResponseStatus(@RequestParam("param") String param) {
   if ("test_responseStatus".equals(param)) {
       throw new CustomException();
   }
   return "main";
}

最后我们调用接口,可以得到,跳转到了4xx.html,但是状态码和message都和我们自己定义的匹配

那么原理是什么呢?我们还是从DispatcherServlet类下的processHandlerException()方法开始看

当我们抛出自定义异常时,由于前面@ControllerAdvice+@ExceptionHandler修饰的类没有指定处理这个异常,所以循环走到下一个异常处理解析器ResponseStatusExceptionResolver

我们分析一下这里的代码

@Nullable
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
    try {
        if (ex instanceof ResponseStatusException) {
            return this.resolveResponseStatusException((ResponseStatusException)ex, request, response, handler);
        }
		// 由于我们自定义异常类使用了@ResponseStatus注解修饰,所以我们这里获取到的status信息不为空
        ResponseStatus status = (ResponseStatus)AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);
        if (status != null) {
            return this.resolveResponseStatus(status, request, response, handler, ex);
        }
		...
protected ModelAndView resolveResponseStatus(ResponseStatus responseStatus, HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) throws Exception {
    // 获取@ResponseStatus注解的code和reason作为状态码和message
	int statusCode = responseStatus.code().value();
    String reason = responseStatus.reason();
    return this.applyStatusAndReason(statusCode, reason, response);
}
protected ModelAndView applyStatusAndReason(int statusCode, @Nullable String reason, HttpServletResponse response) throws IOException {
    if (!StringUtils.hasLength(reason)) {
        response.sendError(statusCode);
    } else {
        String resolvedReason = this.messageSource != null ? this.messageSource.getMessage(reason, (Object[])null, reason, LocaleContextHolder.getLocale()) : reason;
		// 发送/error请求,入参为@ResponseStatus注解的code和reason
        response.sendError(statusCode, resolvedReason);
    }
	// 返回一个modelAndView
    return new ModelAndView();
}

经过debug我们知道,ResponseStatusExceptionResolver这个异常处理解析器返回了一个空的ModelAndView对象给我们,而且还通过response.sendError(statusCode, resolvedReason);发送了/error请求

这样就又走到了上面的第三节处理/error请求的流程中,从而带着我们@ResponseStatus注解的code和reason跳转到了4xx.html页面,这样就能解释为什么4xx.html页面中的状态码和message都是我们自定义的了

如果没有使用上述2种方法处理指定异常或处理我们自己自定义的异常,那么系统就会按照Spring底层的异常进行处理,如 请求方法不支持异常等,都是使用DefaultHandlerExceptionResolver这个异常处理解析器进行处理的

我们分析这个类的doResolveException()方法得知,它最后也会发送/error请求,从而转到4xx.html或者5xx.html页面

3、自定义异常处理解析器

使用@Component注解,并实现HandlerExceptionResolver接口来自定义一个异常处理解析器

package com.decade.exception;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 将优先级提到第一位,Order越小,优先级越高,所以我们这里设置int的最小值
@Order(Integer.MIN_VALUE)
@Component
public class CustomExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        try {
            response.sendError(500, "自己定义的异常");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ModelAndView();
    }
}

当我们把优先级提到最高时,前面的那些异常处理解析器都会失效,这时我们的自定义异常处理解析器可以作为默认的全局异常处理规则

值得注意的是,当代码走到response.sendError时,就会触发/error请求,当你的异常没有人能处理时,也会走tomcat底层触发response.sendError,发送/error请求

到此这篇关于SpringBoot错误处理流程深入详解的文章就介绍到这了,更多相关SpringBoot错误处理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot中异常处理实战记录

    目录 一.背景 二.需求 三.编写一些异常基础代码 四.注意事项 五.总结 六.代码实现 七.参考文档 一.背景 在我们编写程序的过程中,程序中可能随时发生各种异常,那么我们如何优雅的处理各种异常呢? 二.需求 1.拦截系统中部分异常,返回自定义的响应. 比如: 系统发生HttpRequestMethodNotSupportedException异常,我们需要返回如下信息. http的状态码:返回 405 { code: 自定义异常码, message: 错误消息 } 2.实现自定义异常的拦截

  • SpringBoot接口如何统一异常处理

    目录 为什么要优雅的处理异常 实现案例 @ControllerAdvice异常统一处理 Controller接口 运行测试 进一步理解 @ControllerAdvice还可以怎么用? @ControllerAdvice是如何起作用的(原理)? 为什么要优雅的处理异常 如果我们不统一的处理异常,经常会在controller层有大量的异常处理的代码, 比如: @Slf4j @Api(value = "User Interfaces", tags = "User Interfac

  • Springboot项目异常处理及返回结果统一

    目录 背景 返回结果定义 异常的定义 异常的处理 返回结果的处理 完整代码 使用示例 背景 在创建项目的初期,我们需要规范后端返回的数据结构,以便更好地与前端开发人员合作. 比如后端返回的数据为: {  "msg": "请跳转登陆页面", } 此时前端无法确定后端服务的处理结果是成功的还是失败的.在前端展示页面,成功与失败的展示是要作区分的,甚至不同的成功或失败结果要做出不同的展现效果,这也就是我们为什么要对返回结果做出统一规范的原因. 返回结果定义 public

  • SpringBoot异常处理之异常显示的页面问题

    目录 导言 实现步骤 加入thymeleaf依赖 然后创建controller 使用X进行模糊匹配 统一错误页面显示 导言 默认情况下,SpringBoot 项目错误页面如下: 直接这样太丑了,我们实际上线项目时,如果给用户显示这个页面就不是很友好,用户直接不用了. 所以当系统出现异常时应该给用户更加友好的错误页面,下面我们来看具体是如何实现的. 实现步骤 加入thymeleaf依赖 <dependency> <groupId>org.springframework.boot<

  • springboot 全局异常处理和统一响应对象的处理方式

    目录 springboot异常处理 SpringBoot 默认的异常处理机制 SpringBoot 全局异常处理 1. 局部异常处理 2. 全局异常处理 自定义异常 统一响应对象 定义统一的响应对象 枚举信息 响应对象 springboot异常处理 SpringBoot 默认的异常处理机制 默认情况,SpringBoot 提供两种不同响应方式 一种是浏览器客户端请求一个不存在的页面或服务端异常时,SpringBoot默认会响应一个html 另一种是使用postman等调试工具请求不存在的url或

  • springboot处理异常的5种方式

    目录 1.自定义错误页面 2.@ExceptionHandle 注解处理异常 3.@ControllerAdvice+@ExceptionHandler 注解处理异常 4.配置 SimpleMappingExceptionResolver 处理异常 5.自定义 HandlerExceptionResolver 类处理异常 通用异常处理: 1.自定义异常枚举类 2.自定义异常类 3.自定义异常结果处理类 4.全局异常处理 程序的异常:Throwable 严重错误问题:Error     我们不处理

  • SpringBoot优雅地实现全局异常处理的方法详解

    目录 前言 异常工具 异常处理 异常捕捉 前言 在前一节的学习中,慕歌带大家使用了全局结果集返回,通过使用全局结果集配置,优雅的返回后端数据,为前端的数据拿取提供了非常好的参考.同时通过不同的状态码返回,我们能够清晰的了解报错的位置,排除错误.如果大家有需要,可以使用我提供的的同一结果集以及状态码,并且可以使用全局异常拦截,实现异常的标准返回.接下来,我们一起来了解如何使用全局异常处理吧! 异常工具 先定义一个合适 的异常处理类,在之后的异常都会以这种格式返回前端,前端根据我们的异常进行自己的返

  • 如何在SpringBoot项目里进行统一异常处理

    目录 1.处理前 2.进行系统异常全局处理 3.进行自定义异常处理 效果 前言: 需要了解的知识: @ControllerAdvice的作用 1.处理前 异常代码: /** * 根据id获取医院设置 * * @param id 查看的id编号 * @return */ @ApiOperation(value = "根据id获取医院设置") @GetMapping("/findHospById/{id}") public Result findHospById(@Pa

  • SpringBoot详解实现自定义异常处理页面方法

    目录 1.相关介绍 2.代码实现 3.运行测试 1.相关介绍 当发生异常时, 跳转到我们自定义的异常处理页面. SpringBoot中只需在静态资源目录下创建一个error文件夹, 并把异常处理页面放入其中, 页面的命名与异常错误代码对应, 如404.html, 500.html. 5xx.html可以对应所有错误代码为5开头的错误 默认静态资源目录为类路径(resources)下的: /static /public /resources /META-INF/resources 2.代码实现 H

  • SpringBoot错误处理流程深入详解

    目录 一.错误处理 二.底层相关组件 三.异常处理流程 四.定制错误处理逻辑 1.自定义错误页面 2.使用注解或者默认的异常处理 3.自定义异常处理解析器 一.错误处理 默认情况下,Spring Boot提供/error处理所有错误的映射 对于机器客户端(例如PostMan),它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息(如果设置了拦截器,需要在请求头中塞入Cookie相关参数) 对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据

  • Springboot通过lucene实现全文检索详解流程

    目录 建立索引 检索文档 Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具. Lucene全文检索就是对文档中全部内容进行分词,然后对所有单词建立倒排索引的过程.主要操作是使用Lucene的API来实现对索引的增(创建索引).删(删除索引).改(修改索引).查(搜索数据). 假设我们的电脑的目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词.为了实现这种功能,我们首先利用 Lucene 对这个目

  • Spring Boot自定义错误视图的方法详解

    Spring Boot缺省错误视图解析器 Web应用在处理请求的过程中发生错误是非常常见的情况,SpringBoot中为我们实现了一个错误视图解析器(DefaultErrorViewResolver).它基于一些常见的约定,尝试根据HTTP错误状态码解析出错误处理视图.它会在目录/error下针对提供的HTTP错误状态码搜索模板或者静态资源,比如,给定了HTTP状态码404,它会尝试搜索如下模板或者静态资源: /<templates>/error/404.<ext> - 这里<

  • python学习 流程控制语句详解

    ###################### 分支语句 python3.5 ################ #代码的缩进格式很重要 建议4个空格来控制 #根据逻辑值(True,Flase)判断程序的运行方向 # Ture:表示非空的量(String,tuple元组 .list.set.dictonary),所有非零的数字 # False:0,None .空的量 #逻辑表达式 可以包含 逻辑运算符 and or not if: ##################################

  • ThinkPHP实现微信支付(jsapi支付)流程教程详解

    之前写过一篇文章讲了PHP实现微信支付(jsapi支付)流程 ,详见文章:PHP实现微信支付(jsapi支付)流程. 当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录之后访问该目录实现的,但应用到框架中,还是有一些问题,在ThinkPHP中,由于路由规则与支付授权目录有出入,所以会报错.本篇讲讲在TP中集成微信支付的流程. 鹅厂出的SDK和文档,就是让你看不懂,使劲绕,这酸爽用了就知道.文档和SDK不是应该越简单通俗易懂越好么?难道只有使劲重构才能显示出鹅厂程序猿技术的高超咩?额

  • PHP实现微信支付(jsapi支付)流程步骤详解

    最近接触到一个项目,涉及到微信支付,搞微信开发这么久以来,还没搞过支付,之前也就搞过公众号发红包,感谢前辈们的探索,我看了他们的博文,让我少走了很多弯路. 前期准备: 1.微信认证服务号,并且开通了微信支付 2.微信支付SDK,下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 3.登录微信支付平台https://pay.weixin.qq.com/index.php/account/api_cert下载支付证书

  • PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)流程教程详解

    之前有写过几篇文章将微信支付和退款: 1.PHP实现微信支付(jsapi支付)流程 2.ThinkPHP中实现微信支付(jsapi支付)流程 3.PHP实现微信申请退款 这几篇都是使用了微信官方给的PHP版本的SDK,进行支付的时候写代码可以省不少事,步骤也挺简化,但是集成SDK有很多坑,很多人说引入的SDK老报错,或者说官方SDK本身有不少错误,改起来很麻烦,也确实挺麻烦的,对于新手搞支付很容易被绕进去,那么今天就来讲讲不集成支付SDK直接调用支付接口实现支付和退款. 前期准备: 1.当然了,

  • Centos7 Yum安装PHP7.2流程教程详解

    Centos7Yum安装PHP7.2 1.安装源 安装php72w,是需要配置额外的yum源地址的,否则会报错不能找到相关软件包. php高版本的yum源地址,有两部分,其中一部分是epel-release,另外一部分来自webtatic.如果跳过epel-release的话,安装webtatic的时候,会有错误爆出. 所以,这里需要的命令是: rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-rele

  • springboot2.2 集成 activity6实现请假完整流程示例详解

    新手学习记录.写在springboot test 示例  示例代码地址看结尾.后面有带页面的示例. SpringBoot Test无页面简单示例 员工请假流程 员工发起申请,附带请假信息(请假几天) 单位领导审批,如果通过,交付经理审批,不通过,重新申请 经理审批,如果请假天数不超过三天,经理1审批 如果请假天数在3-5天,经理3审批 超过5天,经理2审批 经理审批通过,流程结束,经理审批不通过,员工重新申请 流程图 代码 activiti.cfg.xml为必须文件且数据库连接正确,否则Proc

  • 网络安全渗透测试小程序抓包流程步骤详解

    目录 小程序测试流程 搜索目标小程序 小程序主体信息确认 小程序包获取 PC端 windows端获取小程序包流程 移动端 解包 调试 抓包 小程序测试流程 分为两个方面,解包可以挖掘信息泄露问题.隐藏的接口,抓包可以测试一些逻辑漏洞.API安全问题.两者结合起来就可以边调试边进行测试,更方便于安全测试. 搜索目标小程序 目标搜索不能仅仅局限于主体单位,支撑单位.供应商.全资子公司等都可能是入口点,所以小程序当然也不能放过它们. 小程序主体信息确认 查看小程序账号主体信息,否则打偏了花费了时间不说

随机推荐