Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 367|回复: 0

SpringBoot整合全局异常处理&SpringBoot整合定时任务Task&SpringBoot整合异步任务

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-7-2 14:45:36 | 显示全部楼层 |阅读模式

    ============整合全局异常===========

    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注解查看结果:

    前台:

     

    后台:(单条线程执行)

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-1 13:03 , Processed in 0.072972 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表