SpringBoot整合全局異常處理&SpringBoot整合定時任務Task&SpringBoot整合異步任務


============整合全局異常===========

1.整合web訪問的全局異常

  如果不做全局異常處理直接訪問如果報錯,頁面會報錯500錯誤,對於界面的顯示非常不友好,因此需要做處理。

全局異常處理的類:

package cn.qlq.ExceptionHandler;

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

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class WebExceptionHandler {
    public static final String ERROR_VIEW = "error";

    @ExceptionHandler(value = Exception.class)
    public Object errorHandler(HttpServletRequest reqest, HttpServletResponse response, Exception e) throws Exception {
        e.printStackTrace();
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", reqest.getRequestURL());
        mav.setViewName(ERROR_VIEW);
        return mav;
    }
}

 

攔截到異常之后會跳轉到error頁面error.html:

目錄結構:

內容如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>捕獲全局異常</title>
</head>
<body>
    <h1 style="color: red">發生錯誤:</h1>
    <div th:text="${url}"></div>
    <div th:text="${exception.message}"></div>
</body>
</html>

 

測試:

2.整合ajax全局異常處理

   ajax異常處理就是捕捉到異常之后返回一個封裝的JSON實體,ajax請求根據返回的狀態判斷是否請求成功。

封裝的工具類:

package cn.qlq.utils;

import java.io.Serializable;

public class JSONResultUtil<T> implements Serializable {

    private static final long serialVersionUID = 3637122497350396679L;

    private boolean success;
    private T data;
    private String msg;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public JSONResultUtil(boolean success) {
        this.success = success;
    }

    public JSONResultUtil(boolean success, String msg) {
        super();
        this.success = success;
        this.msg = msg;
    }

    public JSONResultUtil(boolean success, T data, String msg) {
        super();
        this.success = success;
        this.data = data;
        this.msg = msg;
    }

    /**
     * 返回正確結果不帶數據
     * 
     * @return
     */
    public static JSONResultUtil ok() {
        return new JSONResultUtil(true);
    }

    /**
     * 返回錯誤的結果帶錯誤信息
     * 
     * @param msg
     * @return
     */
    public static JSONResultUtil error(String msg) {
        return new JSONResultUtil(false, msg);
    }

}

 

 

Ajax請求的錯誤處理器:

package cn.qlq.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import cn.qlq.utils.JSONResultUtil;

@RestControllerAdvice
public class AjaxExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public JSONResultUtil defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {

        e.printStackTrace();
        return JSONResultUtil.error(e.getMessage());
    }
}

 

測試:

前台JS:

$.ajax({
        url: "/MySpringboot/err/getAjaxerror",
        type: "POST",
        async: false,
        success: function(data) {
            if(data.success) {
                alert("success");
            } else {
                alert("發生異常:" + data.msg);
            }
        },
        error: function (response, ajaxOptions, thrownError) {
            alert("error");       
        }
    });

后台制造除零異常:

    @RequestMapping("/getAjaxerror")
    @ResponseBody
    public JSONResultUtil getAjaxerror() {
        int a = 1 / 0;
        return JSONResultUtil.ok();
    }

 結果:

3.一個通用的全局異常處理器

  不管是web請求還是ajax請求都可以用它處理。內部根據是否是ajax請求返回對應的數據

package cn.qlq.ExceptionHandler;

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

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;

import cn.qlq.utils.JSONResultUtil;

@RestControllerAdvice
public class MyExceptionHandler {
    public static final String ERROR_VIEW = "error";

    @ExceptionHandler(value = Exception.class)
    public Object errorHandler(HttpServletRequest reqest, HttpServletResponse response, Exception e) throws Exception {

        e.printStackTrace();

        if (isAjax(reqest)) {
            return JSONResultUtil.error(e.getMessage());
        } else {
            ModelAndView mav = new ModelAndView();
            mav.addObject("exception", e);
            mav.addObject("url", reqest.getRequestURL());
            mav.setViewName(ERROR_VIEW);
            return mav;
        }
    }

    /**
     * 根據請求頭是否攜帶X-Requested-With參數判斷是否是ajax請求
     * 
     * @param httpRequest
     * @return
     */
    public static boolean isAjax(HttpServletRequest httpRequest) {
        return (httpRequest.getHeader("X-Requested-With") != null
                && "XMLHttpRequest".equals(httpRequest.getHeader("X-Requested-With").toString()));
    }
}

 

 

 

============整合定時任務Task===========

   在springmvc使用的時候使用到的定時任務一般是quartz,也研究過使用過SpringTask。SpringBoot整合Task非常簡單。

(1)@EnableScheduling開啟task

package cn.qlq.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration // 通過該注解來表明該類是一個Spring的配置,相當於一個xml文件
@EnableScheduling
public class SpringTask {

}

 

 (2)通過注解的方式使用task即可。

package cn.qlq.task;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class FirstAnnotationJob {
    private static int count;

    @Scheduled(fixedRate = 10000)
    public void cron() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            System.err.println("InterruptedException " + e);
        }
        System.out.println("spring anno task execute times " + count++);
    }
}

 

結果:

spring anno task execute times 0
spring anno task execute times 1
spring anno task execute times 2

....

關於springTask的使用參考:https://www.cnblogs.com/qlqwjy/p/9960706.html

 

============整合異步任務===========

  開啟異步任務的方式比較簡單 。異步任務的使用場景是:發布消息、發送短信等一些異步任務上,當然異步可以用線程池實現,發送消息可以用MQ框架實現。

(1)@EnableAsync聲明開啟異步任務

package cn.qlq.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration // 通過該注解來表明該類是一個Spring的配置,相當於一個xml文件
//開啟Task
@EnableScheduling
//開啟異步調用方法
@EnableAsync
public class SpringTask {

}

 

(2)編寫異步任務,@Component注入spring,異步的方法加上@Async注解即可

package cn.qlq.task;

import java.util.concurrent.Future;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

@Component
public class AsyncTask {

    @Async
    public Future<Boolean> doTask11() throws Exception {
        long start = System.currentTimeMillis();
        Thread.sleep(1000);
        long end = System.currentTimeMillis();
        System.out.println("任務1耗時:" + (end - start) + "毫秒,線程名字:" + Thread.currentThread().getName());
        return new AsyncResult<>(true);
    }

    @Async
    public Future<Boolean> doTask22() throws Exception {
        long start = System.currentTimeMillis();
        Thread.sleep(700);
        long end = System.currentTimeMillis();
        System.out.println("任務2耗時:" + (end - start) + "毫秒,線程名字:" + Thread.currentThread().getName());
        return new AsyncResult<>(true);
    }

    @Async
    public Future<Boolean> doTask33() throws Exception {
        long start = System.currentTimeMillis();
        Thread.sleep(600);
        long end = System.currentTimeMillis();
        System.out.println("任務3耗時:" + (end - start) + "毫秒,線程名字:" + Thread.currentThread().getName());
        return new AsyncResult<>(true);
    }
}

 

(3)Controller層調用異步方法:

package cn.qlq.action;

import java.util.concurrent.Future;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.qlq.task.AsyncTask;


@RestController
@RequestMapping("tasks")
public class AsyncTaskController {

    @Autowired
    private AsyncTask asyncTask;

    @RequestMapping("test1")
    public String test1() throws Exception {

        long start = System.currentTimeMillis();

        Future<Boolean> a = asyncTask.doTask11();
        Future<Boolean> b = asyncTask.doTask22();
        Future<Boolean> c = asyncTask.doTask33();

        while (!a.isDone() || !b.isDone() || !c.isDone()) {
            if (a.isDone() && b.isDone() && c.isDone()) {
                break;
            }
        }

        long end = System.currentTimeMillis();

        String times = "任務全部完成,總耗時:" + (end - start) + "毫秒";
        System.out.println(times);

        return times;
    }
}

  上面執行asyncTask.doTaskXX的時候是異步執行的,相當於三個方法異步執行,下面的while循環直到三個方法都執行完畢。

 

測試:

前台訪問:

后台控制台:(發現是通過多線程執行)

 

如果去掉上面三個異步方法的@Async注解查看結果:

前台:

 

后台:(單條線程執行)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM