• Java生鲜电商平台-异常模块的设计与架构


    Java生鲜电商平台-异常模块的设计与架构

    说明:任何一个软件系统都会出现各式各样的异常与错误,我们需要根据异常的情况进行捕获与分析,改善自己的代码,让其更加的稳定的,快速的运行,那么作为一个

    B2B的Java开源生鲜电商平台,我们的异常需要思考以下几个维度。

    1. 运行的代码异常

        说明:代码在运行的过程中,难免出现各种异常与错误,我们采用Log4j进行日志的记录。

                  在分层代码解耦过程中,我们统一在Controller进行异常的捕获与日志记录。

    相关的运行的代码异常架构如下:

        /**
         * (商家店铺)商品信息列表
         * @param request
         * @param response
         * @return
         */
        @RequestMapping(value = "/goods/list", method = { RequestMethod.GET})
        public JsonResult goodsList(HttpServletRequest request, HttpServletResponse response) {
            try
            {
                //业务逻辑处理
                return new JsonResult(JsonResultCode.FAILURE, "系统错误,请稍后重试","");
            }catch(Exception ex){
                logger.error("[GoodsController][goodsList] exception :",ex);
                return new JsonResult(JsonResultCode.FAILURE, "系统错误,请稍后重试","");
            }
        }

    说明:由于spring的事物控制在service层,所以service层不抓取异常。所有的异常都在controller进行抓取,而且抓取的是任何的异常

               异常的记录采用某个类[]某个方法[] exception,这种方式,然后把所有的异常的堆栈信息进行打印出来,方便进行查看与分析,定位等

    2. 全局异常

         说明:对于有可能出现的全局异常,我们采用Spring的全局异常处理器,进行代码的统一处理。 

       2.1,对于业务层的异常,我们采用自定义异常进行获取

      核心代码如下:

         

    /**
     * service异常,业务异常继续于当前接口
     * 
     */
    public class ServiceException extends RuntimeException {
    
        private static final long serialVersionUID = 4875141928739446984L;
    
        /**
         * 错误码
         */
        protected String code;
    
        /**
         * 错误信息
         */
        protected String message;
    
        public ServiceException(String code, String message) {
            super();
            this.code = code;
            this.message = message;
        }
    
        public ServiceException(String code, String message, Throwable t) {
            super();
            this.code = code;
            this.message = message;
        }
    
        public ServiceException(String message) {
            super(message);
            this.message = message;
        }
    
        public ServiceException(String message, Throwable t) {
            super(message, t);
            this.message = message;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        @Override
        public String toString() {
            return "ServiceException [code=" + code + ", message=" + message + "]";
        }

       2.2 对于全局的异常,我们采用spring的统一进行处理,只需要在代码中进行异常的抛出即可

          核心代码如下:

         

    /**
     * 全局异常处理类.对后台直接抛往前台页面的异常进行封装处理.
     */
    public class ExceptionHandler extends SimpleMappingExceptionResolver {
    
        private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);
    
        @Override
        protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                Exception ex) {
    
            ModelAndView mv = super.doResolveException(request, response, handler, ex);
    
            String url = WebUtils.getPathWithinApplication(request);
    
            logger.error("controller error.url=" + url, ex);
    
            /* 使用response返回 */
            response.setStatus(HttpStatus.OK.value()); // 设置状态码
            response.setContentType(MediaType.APPLICATION_JSON_VALUE); // 设置ContentType
            response.setCharacterEncoding("UTF-8"); // 避免乱码
            response.setHeader("Cache-Control", "no-cache, must-revalidate");
            
            JsonResult jsonResult=new JsonResult(JsonResultCode.FAILURE,"系统错误,请联系管理员","");
            
            if(ex instanceof ServiceException)
            {
                ServiceException serviceException=(ServiceException)ex;
                String code=serviceException.getCode();
                String message=serviceException.getMessage();
                jsonResult=new JsonResult(code,message,"");
            }
            try 
            {
                PrintWriter printWriter = response.getWriter();
                printWriter.write(JSONObject.fromObject(jsonResult).toString());
                printWriter.flush();
                printWriter.close();
            } catch (IOException e) 
            {
                logger.error("与客户端通讯异常:" + e.getMessage(), e);
            }
            logger.error("异常:" + ex.getMessage(), ex);
            return mv;
        }
    }

    spring中还需要加上一段这样的配置:

    <!-- 全局异常处理.-->
    <bean id="exceptionHandler" class="com.netcai.buyer.exception.ExceptionHandler"/>   

        

    3. 代码格式方面

       说明:我们控制所有的请求的接口,都需要返回JsonResult对象,另外,我们规定“200”字符串表示请求成功,非“200”表示失败

        相关的代码贴出来,请大家分享:

        

    /**
     *  Controller层的 json格式对象
     */
    public class JsonResult implements java.io.Serializable {
    
        private static final long serialVersionUID = 1L;
        
        /**
         * 返回的编码
         */
        private String code;
        
        /**
         * 返回的信息
         */
        private String message;
        
        /***
         * 返回的对象
         */
        private Object object;
    
        public JsonResult() {
            super();
        }
        
        public JsonResult(String code, String message, Object object) {
            super();
            this.code = code;
            this.message = message;
            this.object = object;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        public Object getObject() {
            return object;
        }
    
        public void setObject(Object object) {
            this.object = object;
        }
    }

    相关的JsonResultCode对象如下:

    /**
     */
    public class JsonResultCode {
    
        /**成功**/
        public static final String SUCCESS="200";
    
        /**失败**/
        public static final String FAILURE="201";
    }

    最终形成了一套完整的数据量的处理,另外还有特殊的情况,比如:404,500等等其他的业务请求,我们应该如何处理的?

    由于我们是运行在tomcat下面的,我们在web.xml进行了配置。

    代码如下

    <error-page>
            <exception-type>java.lang.Throwable</exception-type>
            <location>/error_500</location>
        </error-page>
        <error-page>
            <exception-type>java.lang.Exception</exception-type>
            <location>/error_404</location>
        </error-page>
        <error-page>
            <error-code>500</error-code>
            <location>/error_500</location>
        </error-page>
        <error-page>
            <error-code>501</error-code>
            <location>/error_500</location>
        </error-page>
        <error-page>
            <error-code>502</error-code>
            <location>/error_500</location>
        </error-page>
        <error-page>
            <error-code>404</error-code>
            <location>/error_404</location>
        </error-page>
        <error-page>
            <error-code>403</error-code>
            <location>/error_404</location>
        </error-page>
        <error-page>
            <error-code>400</error-code>
            <location>/error_404</location>
        </error-page>

    我们把可能出现的任何情况都进行了拦截,然后交给spring来处理这种请求,最终形成一套自己的特殊异常处理

    代码如下:

    /**
     * 错误统一处理
     */
    @RestController
    public class ErrorController {
    
        /**
         * 请求异常404
         * @return
         * @throws Exception
         */
        @RequestMapping(value = "/error_404", method = { RequestMethod.GET, RequestMethod.POST })
        public JsonResult error_404() throws Exception 
        {
            return new JsonResult(JsonResultCode.FAILURE, "404请求找不到请求", "");
        }
        
        /**
         * 服务器异常
         * @return JsonResult
         */
        @RequestMapping(value = "/error_500", method = { RequestMethod.GET, RequestMethod.POST })
        public JsonResult error_500()
        {    
            return new JsonResult(JsonResultCode.FAILURE, "500服务器内部错误", "");
        }
    }

    总结:我们通过3种情况来进行了所有可能异常的处理,全局异常,业务代码异常,特殊情况异常,架构封装,统一的数据返回与处理等等,进行了完美的结合,该项目运行一年半以来,采用这种异常架构后,从没出现过返回给app什么500错误或者其他乱七八糟的错误,依然是正确的JsonResult对象,APP那边也不用处理特殊情况,一举两得

  • 相关阅读:
    Codeforces 798C. Mike and gcd problem 模拟构造 数组gcd大于1
    Codeforces 796C. Bank Hacking
    Codeforces 792B. Counting-out Rhyme
    gym 101164 H.Pub crawl 凸包
    hdu 6053 TrickGCD 筛法
    hdu 6041 I Curse Myself 无向图找环+优先队列
    bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分
    codeforces gym 101164 K Cutting 字符串hash
    树链剖分求lca
    UESTC 1697 简单GCD问题(一) 筛法
  • 原文地址:https://www.cnblogs.com/jurendage/p/9075219.html
Copyright © 2020-2023  润新知