全局异常处理及自定义异常:ErrorController与@ControllerAdvice区别和用法_abstracterrorcontroller-程序员宅基地

技术标签: SpringBoot  

 

参考资料

  1. springboot继承AbstractErrorController实现全局的异常处理
    https://blog.csdn.net/qq_29684305/article/details/82286469
  2. spring boot 原生错误处理ErrorController
    https://blog.csdn.net/shenyunsese/article/details/53390116
  3. @ControllerAdvice 拦截异常并统一处理
    https://my.oschina.net/langwanghuangshifu/blog/2246890

ErrorController

在springboot项目中当我们访问一个不存在的url时经常会出现以下页面

在postman访问时则是以下情况

image

image

对于上面的情况究竟是什么原因造成呢,实际上当springboot项目出现异常时,默认会跳转到/error,而/error则是由BasicErrorController进行处理,其代码如下

@Controller
@RequestMapping({
     "${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {
    private final ErrorProperties errorProperties;

    public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
        this(errorAttributes, errorProperties, Collections.emptyList());
    }

    public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, errorViewResolvers);
        Assert.notNull(errorProperties, "ErrorProperties must not be null");
        this.errorProperties = errorProperties;
    }

    public String getErrorPath() {
        return this.errorProperties.getPath();
    }

    @RequestMapping(
        produces = {
     "text/html"}
    )
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        return modelAndView == null ? new ModelAndView("error", model) : modelAndView;
    }

    @RequestMapping
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = this.getStatus(request);
        return new ResponseEntity(body, status);
    }

    protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
        IncludeStacktrace include = this.getErrorProperties().getIncludeStacktrace();
        if (include == IncludeStacktrace.ALWAYS) {
            return true;
        } else {
            return include == IncludeStacktrace.ON_TRACE_PARAM ? this.getTraceParameter(request) : false;
        }
    }

    protected ErrorProperties getErrorProperties() {
        return this.errorProperties;
    }
}
  • 可见BasicErrorController是一个控制器,对/error进行处理
  • BasicErrorController根据Accept头的内容,输出不同格式的错误响应。比如针对浏览器的请求生成html页面,针对其它请求生成json格式的返回。字段为accept的text/html的内容来判断
  • 我们也可自定义ErrorController来实现自己对错误的处理,例如浏览器访问也返回json字符串(返回text/html),或自定义错误页面,不同status跳转不同的页面等,同时其他请求也可自定义返回的json格式

下面是自己写的一个ErrorController

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;
import com.xuecheng.framework.model.response.ErrorCode;
import com.xuecheng.framework.model.response.ResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * web错误 全局处理
 * @author jiangwf
 *
 */
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;

@Controller
public class InterfaceErrorController implements ErrorController {
    private static final String ERROR_PATH="/error";
    private ErrorAttributes errorAttributes;

    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }
    @Autowired
    public InterfaceErrorController(ErrorAttributes errorAttributes) {
        this.errorAttributes=errorAttributes;
    }

    /**
     * web页面错误处理
     */
    @RequestMapping(value=ERROR_PATH,produces="text/html")
    @ResponseBody
    public String errorPageHandler(HttpServletRequest request,HttpServletResponse response) {
        ServletWebRequest requestAttributes =  new ServletWebRequest(request);
        Map<StringObject> attr = this.errorAttributes.getErrorAttributes(requestAttributes, false);
        JSONObject jsonObject = new JSONObject();
        ErrorCode errorCode = new ErrorCode(false, (int) attr.get("status"), (String) attr.get("message"));
        return JSONObject.toJSONString(errorCode);
    }

    /**
     * 除web页面外的错误处理,比如json/xml等
     */
    @RequestMapping(value=ERROR_PATH)
    @ResponseBody
    public ResultCode errorApiHander(HttpServletRequest request) {
        ServletWebRequest requestAttributes = new ServletWebRequest(request);
        Map<StringObject> attr=this.errorAttributes.getErrorAttributes(requestAttributes, false);
        return new ErrorCode(false, (int)attr.get("status"), (String) attr.get("message"));
    }

}
  • 当是浏览器访问时返回json字符串image

    image

  • 当是其他请求时返回自定义的ErrorCodeimage

    image

  • ErrorCode代码如下
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

@ToString
@Data
@AllArgsConstructor
public class ErrorCode implements ResultCode{

    private boolean success;

    private int code;

    private String message;


    @Override
    public boolean success() {
        return false;
    }

    @Override
    public int code() {
        return 0;
    }

    @Override
    public String message() {
        return null;
    }
}
  • ResultCode代码如下
public interface ResultCode {
    //操作是否成功,true为成功,false操作失败
    boolean success();
    //操作代码
    int code();
    //提示信息
    String message();

}

@ControllerAdvice

  • 上面我们提到ErrorController可对全局错误进行处理,但是其获取不到异常的具体信息,同时也无法根据异常类型进行不同的响应,例如对自定义异常的处理
  • 而@ControllerAdvice可对全局异常进行捕获,包括自定义异常
  • 需要清楚的是,其是应用于对springmvc中的控制器抛出的异常进行处理,而对于404这样不会进入控制器处理的异常不起作用,所以此时还是要依靠ErrorController来处理

 

问题:

 

  • 实际上,当出现错误,如获取值为空或出现异常时,我们并不希望用户看到异常的具体信息,而是希望对对应的错误和异常做相应提示
  • 在MVC框架中很多时候会出现执行异常,那我们就需要加try/catch进行捕获,如果service层和controller层都加上,那就会造成代码冗余

 

解决方法:

 

  • 统一返回的数据格式,如上的ResultCode,可实现其做更多扩展,对于程序的可预知错误,我们采取抛出异常的方式,再统一处理
  • 我们在编程时的顺序是先校验判断,有问题则抛出异常信息,最后执行具体的业务操作,返回成功信息
  • 在统一异常处理类中去捕获异常,无需再代码中try/catch,向用户返回统一规范的响应信息

异常处理流程

系统对异常的处理使用统一的异常处理流程:

  1. 自定义异常类型
  2. 自定义错误代码及错误信息
  3. 对于可预知的异常由程序员在代码中主动抛出,有SpringMVC统一捕获
    可预知异常是程序员在代码中手动抛出本系统定义的特点异常类型,由于是程序员抛出的异常,通常异常信息比较齐全,程序员在抛出时会指定错误代码及错误信息,获取异常信息也比较方便
  4. 对于不可预知的异常(运行时异常)由SpringMVC统一捕获Exception类型的异常
    不可预知的异常通常是由于系统出现bug、或一些不可抗拒的错误(比如网络中断、服务器宕机等),异常类型为RuntimeException类型(运行时异常)
  5. 可预知异常及不可预知异常最终都会采用统一的信息格式(错误代码+错误信息)来表示,最终也会随请求响应给客户端

异常抛出及处理流程

image

image

  1. 在controller、service、dao中程序员抛出自定义异常;SpringMVC框架抛出框架异常类型
  2. 统一由异常捕获类捕获异常并进行处理
  3. 捕获到自定义异常则直接取出错误代码及错误信息,响应给用户
  4. 捕获到非自定义异常类型首先从Map中找该异常类型是否对应具体的错误代码,如果有则取出错误代码和错误信息并响应给用户,如果从Map中占不到异常类型所对应的错误代码则统一为99999错误代码并响应给用户
  5. 将错误代码及错误信息以json格式响应给用户

下面就开始我们的异常处理编程

一、可预知异常

  1. 自定义异常类
import com.xuecheng.framework.model.response.ResultCode;
import jdk.nashorn.internal.objects.annotations.Getter;

/**
 * @Author: jiangweifan
 * @Date: 2019/3/4 20:06
 * @Description:
 */
public class CustomException extends RuntimeException {

    private ResultCode resultCode;

    public CustomException(ResultCode resultCode) {
        super("错误代码:" + resultCode.code()+" 错误信息:" + resultCode.message());
        this.resultCode = resultCode;
    }

    public ResultCode getResultCode() {
        return resultCode;
    }
}
  1. 自定义异常抛出类
import com.xuecheng.framework.model.response.ResultCode;

/**
 * @Author: jiangweifan
 * @Date: 2019/3/4 20:09
 * @Description:
 */
public class ExceptionCast {

    public static void cast(ResultCode resultCode, boolean condition) {
        if (condition) {
            throw new CustomException(resultCode);
        }
    }
}
  1. 异常捕获类
    使用@ControllerAdvice和@ExceptionHandler注解来捕获指定类型的异常
import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.SocketTimeoutException;

/**
 * @Author: jiangweifan
 * @Date: 2019/3/4 20:13
 * @Description:
 */
@ControllerAdvice
@Slf4j
public class ExceptionCatch {

    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException e) {
        log.error("catch exception : {} \r\nexception", e.getMessage(), e);
        ResponseResult responseResult = new ResponseResult(e.getResultCode());
        return responseResult;
    }

}

4.1 定义响应数据格式

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * @Author: mrt.
 * @Description:
 * @Date:Created in 2018/1/24 18:33.
 * @Modified By:
 */
@Data
@ToString
@NoArgsConstructor
public class ResponseResult implements Response {

    //操作是否成功
    boolean success = SUCCESS;

    //操作代码
    int code = SUCCESS_CODE;

    //提示信息
    String message;

    public ResponseResult(ResultCode resultCode){
        this.success = resultCode.success();
        this.code = resultCode.code();
        this.message = resultCode.message();
    }

    public static ResponseResult SUCCESS(){
        return new ResponseResult(CommonCode.SUCCESS);
    }
    public static ResponseResult FAIL(){
        return new ResponseResult(CommonCode.FAIL);
    }

}

其中Response代码如下
public interface Response {
    public static final boolean SUCCESS = true;
    public static final int SUCCESS_CODE = 10000;
}

4.2 定义错误代码(ResultCode上文已给出)

import com.xuecheng.framework.model.response.ResultCode;
import lombok.ToString;

/**
 * Created by mrt on 2018/3/5.
 */
@ToString
public enum CmsCode implements ResultCode {
    CMS_ADDPAGE_EXISTSNAME(false,24001,"页面名称已存在!"),
    CMS_GENERATEHTML_DATAURLISNULL(false,24002,"从页面信息中找不到获取数据的url!"),
    CMS_GENERATEHTML_DATAISNULL(false,24003,"根据页面的数据url获取不到数据!"),
    CMS_GENERATEHTML_TEMPLATEISNULL(false,24004,"页面模板为空!"),
    CMS_GENERATEHTML_HTMLISNULL(false,24005,"生成的静态html为空!"),
    CMS_GENERATEHTML_SAVEHTMLERROR(false,24005,"保存静态html出错!"),
    CMS_COURSE_PERVIEWISNULL(false,24007,"预览页面为空!"),
    CMS_TEMPLATEFILE_ERROR(false,24008,"模板文件需要.ftl后缀!"),
    CMS_TEMPLATEFILE_NULL(false,24009,"模板文件为空!"),
    CMS_TEMPLATEFILE_EXCEPTION(false,24010,"解析模板文件异常!"),
    CMS_TEMPLATEFILE_FAIL(false,24011,"模板文件存储失败!"),
    CMS_TEMPLATEFILE_DELETE_ERROR(false,24012,"模板文件删除失败!"),
    CMS_Config_NOTEXISTS(false,24013,"不存在该数据模型!"),
    CMS_PAGE_NULL(false,24014,"不存在该页面数据!"),
    CMS_GENERATEHTML_CONTENT_FAIL(false,24014,"获取页面模板失败!");
    //操作代码
    boolean success;
    //操作代码
    int code;
    //提示信息
    String message;
    private CmsCode(boolean success, int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return success;
    }

    @Override
    public int code() {
        return code;
    }

    @Override
    public String message() {
        return message;
    }
}
  1. 在方法中抛出异常进行测试
@GetMapping("/list/{page}/{size}")
public QueryResponseResult findList(@PathVariable("page") int page, @PathVariable("size")int size, QueryPageRequest queryPageRequest) {
    ExceptionCast.cast(CmsCode.CMS_COURSE_PERVIEWISNULL, queryPageRequest == null);
    return pageService.findList(page,size,queryPageRequest);
}

最终方法得到以下结果
 

image

image

二、不可预知异常处理

  1. 在异常捕获类中添加对Exception类型异常的捕获,完整代码如下
import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.SocketTimeoutException;

/**
 * @Author: jiangweifan
 * @Date: 2019/3/4 20:13
 * @Description:
 */
@ControllerAdvice
@Slf4j
public class ExceptionCatch {

    //使用EXCEPTIOS存放异常类型 和错误代码的映射,ImmutableMap的特点是已创建就不可变,并且线程安全
    private static ImmutableMap<Class<? extends  Throwable>, ResultCode> EXCEPTIOS;
    //是由builder来构建一个异常类型和错误代码的映射
    private static ImmutableMap.Builder<Class<? extends  Throwable>, ResultCode> builder =
            ImmutableMap.builder();

    static {
        //初始化基础类型异常与错误代码的映射
        builder.put(NullPointerException.class, CommonCode.NULL);
        builder.put(SocketTimeoutException.class, CommonCode.NULL);
    }

    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException e) {
        log.error("catch exception : {} \r\nexception", e.getMessage(), e);
        ResponseResult responseResult = new ResponseResult(e.getResultCode());
        return responseResult;
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception e) {
        log.error("catch exception : {} \r\nexception", e.getMessage(), e);
        if (EXCEPTIOS == null) {
            EXCEPTIOS = builder.build();
        }
        final ResultCode resultCode = EXCEPTIOS.get(e.getClass());
        if (resultCode != null) {
            return new ResponseResult(resultCode);
        } else {
            return new ResponseResult(CommonCode.SERVER_ERROR);
        }

    }

}
  • 对于不可预知异常的处理,我们采取先从定义好的Map获取该异常类型对应的错误代码和错误信息,若没有则统一返回CommonCode.SERVER_ERROR
  • 对于CommonCode代码如下(ResultCode上文已给出)
import lombok.ToString;

/**
 * @Author: mrt.
 * @Description:
 * @Date:Created in 2018/1/24 18:33.
 * @Modified By:
 */

@ToString
public enum CommonCode implements ResultCode{

    SUCCESS(true,10000,"操作成功!"),
    FAIL(false,19999,"操作失败!"),
    UNAUTHENTICATED(false,10001,"此操作需要登陆系统!"),
    UNAUTHORISE(false,10002,"权限不足,无权操作!"),
    NULL(false,10003,"空值异常!"),
    TIMEOUT(false10004"服务器连接超时!"),
    SERVER_ERROR(false,99999,"抱歉,系统繁忙,请稍后重试!");
//    private static ImmutableMap<Integer, CommonCode> codes ;
    //操作是否成功
    boolean success;
    //操作代码
    int code;
    //提示信息
    String message;
    private CommonCode(boolean success,int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return success;
    }
    @Override
    public int code() {
        return code;
    }

    @Override
    public String message() {
        return message;
    }
}
  1. 方法中进行测试
 @GetMapping("/list/{page}/{size}")
public QueryResponseResult findList(@PathVariable("page") int page, @PathVariable("size")int size, QueryPageRequest queryPageRequest) {
    int a= 1/0;
    return pageService.findList(page,size,queryPageRequest);
}

浏览器访问结果如下:
 

image

image

至此我们完成了对全局异常的处理

欢迎关注公众号,后续文章更新通知,一起讨论技术问题 。

公众号二维码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jwf111/article/details/88571067

智能推荐

英特尔发布重大技术架构的改变和创新,面向CPU、GPU和IPU_处理器架构从哪些方面改进-程序员宅基地

文章浏览阅读4.2k次。在2021年英特尔架构日上,英特尔公司高级副总裁兼加速计算系统和图形事业部总经理Raja Koduri携手多位英特尔架构师,全面介绍了两种全新x86内核架构的详情;英特尔首个性能混合架构,代号“Alder Lake”,以及智能的英特尔硬件线程调度器;专为数据中心设计的下一代英特尔至强可扩展处理器Sapphire Rapids;基础设施处理器(IPU);即将推出的显卡架构,包括Xe HPG微架构和Xe HPC微架构,以及Alchemist SoC, Ponte Vecchio SoC。这些新架构将为._处理器架构从哪些方面改进

PointConv:基于3D点云的深度卷积网络_点云不能用卷积网络吗-程序员宅基地

文章浏览阅读3.8k次。原文首发于微信公众号「3D视觉工坊」——PointConv:基于3D点云的深度卷积网络本文出自知乎:https://zhuanlan.zhihu.com/p/69597887?utm_source=wechat_session&utm_medium=social&utm_oi=1135649954939883520原文:PointConv: Deep Convol..._点云不能用卷积网络吗

遥感影像镶嵌拼接_qmosaic-程序员宅基地

文章浏览阅读8.6k次,点赞3次,收藏34次。软件下载地址:https://pan.baidu.com/s/1dt0yDUsAork9LnLnZTwCgw需要百度网盘下载密码,留言邮箱地址。或联系联系QQ:1257396288​首先加载需要处理的影像,如下所示:然后点击菜单栏中的“生成镶嵌线”,具体参数设置如下:1.自动生成镶嵌线点击“生成镶嵌线”按钮,弹出如下对话框:处理方式:分..._qmosaic

UCOSII基础之数据结构-程序员宅基地

文章浏览阅读157次。数据结构在对操作系统的理解是有很大的帮助的,而且也是必须要掌握的。在ucosII中也有很多的数据结构的应用。数据结构的参考书目主要是严蔚敏老师的数据结构教材了。网上也应该能找到严蔚敏老师的数据结构的视频。可以去电驴去慢慢拖。我已经在六维空间里下过了,但是没有看过。一直放在硬盘里面存着。数据结构中主要的部分就是线性表,队列,堆栈,串,数组,树和二叉树,图,还有一些排序和查找的快速算法。这一些东西..._ucos ii信号量运用的数据结构

Android9设备打开WIFI热点,Android9.0Wifi热点开启流程梳理-程序员宅基地

文章浏览阅读2.3k次。Android9.0中对热点做了较大改动,将热点很大程度从Wifi中剥离出来了。下面我们看一下热点是怎么开启的。首先是在WifiTetherSettings中,调用startTether()函数,可以看到startTether函数中主要是调用了WifiTetherSwitchBarController.java中的startTether()函数。源码路径:http://androidxref.co..._android10 热点打开

【论文笔记】DenseNet_densenet的降采样层是什么-程序员宅基地

文章浏览阅读1k次。介绍卷积神经网络(CNNs)已成为视觉物体识别领域占据主导的机器学习方法。虽然訪方法最初于20年前提出,但直到最近由于硬件性能和网络结构上的改善才真正意义上实现深层的CNNs训练。 随着CNNs层次越来越深,新的问题随之出现。输入信息或者说梯度当经过众多层到达网络底端后会消失。这篇论文提出了一种新的连接模式:为最大化网络之间的信息流动,我们将网络中的每一层与其它层直接相连。每..._densenet的降采样层是什么

随便推点

2020-08-24_"</span><span dir=\"ltr\" style=\"font-style: norm-程序员宅基地

文章浏览阅读139次。1.1基本概念CSS(Cascading Style Sheet) 层叠样式表,为了实现页面内容和表现形式的分离。层叠的含义是可以对一个元素多次设置样式,最后的结果是多次样式叠加的结果,如果有冲突,以后面的样式为准。1.2 基本语法选择器{属性名1:属性值1;属性名2:属性值2;属性名3:属性值3;……}选择器说明该样式施加于哪些元素;属性名和属性值说明是样式内容;一般一行定义一条样式,当然也可以写在一行上,但每条样式都序号加上“;”推荐用小写命名。<_"

【观察】解读Kyligence智能数据云战略,打造新一代数据管理“底座”-程序员宅基地

文章浏览阅读249次。申耀的科技观察读懂科技,赢取未来!众所周知,随着云计算、大数据、人工智能、物联网等新技术在各行各业更加广泛的普及与应用,在催生越来越多数据量产生的同时,也让数据的管理和价值挖掘变得愈加复杂..._kyligence

解决js在浏览器中文乱码问题以及js、jsp没有正确加载问题_js sources乱码-程序员宅基地

文章浏览阅读1.9k次。部署项目时js中文乱码问题解决添加修改js、jsp文件没有对应结果问题在做项目的时候,引入了js文件,发现该模块在浏览器中的中文显示乱码,但是其它中文都好好的在浏览器中F12->Sources->page那里看自己项目的js文件,发现其中的中文都是乱码,真的很烦啊。首先肯定的是编码格式出问题了,但是按照网友说的查看js的编码格式也确实是utf-8,项目也均是utf-8。解决..._js sources乱码

ESP32 开发笔记(七)LittlevGL PC Simulator 配置_esp sdl2-程序员宅基地

文章浏览阅读3k次,点赞2次,收藏4次。PC Simulator 配置视频教程:How to Run Littlev Graphics Library in PC Simulator (Linux)PC simulatorYou can try out the Littlev Graphics Library using only your PC without any development board. Write a ..._esp sdl2

static 详解_vb 释放静态变量-程序员宅基地

文章浏览阅读1.6k次。static像在VB,C,C++,Java中我们可以看到static作为关键字和函数出现,在其他的高级计算机语言如FORTRAN、ALGOL、COBOL、BASIC、LISP、SNOBOL、PL/1、Pascal、PROLOG、Ada等语言中也是有出现的,只是有着不同的作用,对于其具体作用,读者有需要的时候是可以具体查阅的鉴于时间问题今天我就不一一罗列了。C++中的static简介C#与C+..._vb 释放静态变量

Linux进程间通信 --eventfd_eventfd epoll poll select inotify-程序员宅基地

文章浏览阅读293次。进程间测通信 --eventfd最近在学习多线程网络库muduo时,新学了一种新的进程通信方法eventfd。它是从LINUX 2.6.27版本开始增加的,主要用于进程或者线程间的通信(如通知/等待机制的实现)。我们知道,在进行IO多路复用的时候,比如select、poll、epoll等,线程会阻塞在这些监听函数上面。有时候,我们需要在没有监听事件到来时,将线程从阻塞的监听函数中唤醒。常用的唤醒方法是:建立一个管道,将管道的一端置于监听函数上,当我们想要唤醒线程时,像管道的另一端写入数据。even_eventfd epoll poll select inotify