LCMS异常处理

参考文章来源:[leaforbook - 如何正确使用Java异常处理机制]
http://leaforbook.com/blog/jexception/original/practical.html

概述

Java异常处理机制的目的至少有三个:
一是归类处理不同的异常,
二是提供足够的信息方便调试,
三是让主流程代码保持整洁。

  • 代码异常
    指的是运行期异常,不需要显示声明,比如空指针、类型转换异常等等,这些异常可以通过代码的控制来规避掉

  • 业务异常
    lcms中定义了BusinessException、UniqueKeyException等异常类,用来处理业务异常

异常的处理

  • 异常均要有error日志
    log.error(“异常信息”, e)

  • 不知道如何处理的情况下,异常向上抛出
    throw e;

  • 业务需要情况下,异常向上转义并抛出
    throw new BusinessException(“异常信息”, e);

  • 使用异常来进行验证信息的返回

    • Excel导入验证、webservice接口验证等
      Excel导入需呀验证一系列规则,比如各单元格内容是否必填、格式是否符合要求等

    外部数据导入一般都是要求验证,争取则处理,不正确则返回错误信息。
    在不定义返回多值(返回Map或ResultCollection对象)的情况下
    如果不使用异常机制下,则需要返回一个个字符串,来作为判断的依据
    而且后面获取数据的时候还要再次读取一次

    /**
     * Excel人员导入数据必填验证
     * @param sheet
     * @return 
     * @throws Exception
     */
    public static String personExcelDataRequired(HSSFSheet sheet)throws Exception{

        for (int i = 1; i <= sheet.getLastRowNum(); i++) {//从第二行开始
            int m=i+1;//行号
            HSSFRow row = sheet.getRow(i);
            if(!ExcelUtil.isBlankRow(row)){//不为空行
                //每一行列数为6验证
                int rowFirst=row.getFirstCellNum();//第一列index
                int rowLast=row.getLastCellNum();//最后一列index
                if(rowFirst==0 || rowFirst==1){//序号 可以不填
                    if(rowLast!=7){
                        return "第"+m+"行"+ImportConstants.DATA_COLUMN_ERROR;
                    }
                }else {//第一列和第二列为空
                    return "第"+m+"行"+ImportConstants.DATA_ORIGN_COLUMN_ERROR;
                }
                //每一行非空、格式、字符长度验证
                String message="";
                for(int j=1;j<=row.getLastCellNum();j++){//从第二列"姓名"开始验证
                    HSSFCell cell=row.getCell(j);
                    switch(j){
                    //姓名
                    case 1:message=ExcelUtil.validateStringCell(cell,20);
                        if(!message.equals("0")){
                            return "第"+m+"行,"+PersonConstants.EXCELHEAD_CELL_1+message;
                        }
                        break;
                    //性别
                    case 2:message=ExcelUtil.validateStringCell(cell,4);
                        if(!message.equals("0")){
                            return "第"+m+"行,"+PersonConstants.EXCELHEAD_CELL_2+message;
                        }
                        break;      
                    //身份证号码
                    case 3:message=ExcelUtil.validateStringCell(cell,20);
                        if(!message.equals("0")){
                            return "第"+m+"行,"+PersonConstants.EXCELHEAD_CELL_3+message;
                        }
                        break;
                    //单位
                    case 4:message=ExcelUtil.validateStringCell(cell,50);
                        if(!message.equals("0")){
                            return "第"+m+"行,"+PersonConstants.EXCELHEAD_CELL_4+message;
                        }
                        break;
                    //培训日期
                    case 5:message=ExcelUtil.validateStringCell(cell,50);
                        if(!message.equals("0")){
                            return "第"+m+"行,"+PersonConstants.EXCELHEAD_CELL_5+message;
                        }
                        break;
                    //上岗证号
                    //case 6:message=ExcelUtil.validateStringOrNumricCell(cell,12);
                    case 6:message=ExcelUtil.validateStringCell(cell,10);
                        if(!message.equals("0")){
                            return "第"+m+"行,"+PersonConstants.EXCELHEAD_CELL_6+message;
                        }
                        break;

                    default:
                        break;
                    }
                }
            }
        }
        return "0";
    }
/**
     * 获得Excel personList
     * @param sheet
     * @return
     * @throws Exception
     */
    public static List<Person> getPersonExcelList(HSSFSheet sheet) throws Exception{
        List<Person> list=new ArrayList<Person>();
        //遍历每一行
        for(int i=1;i<=sheet.getLastRowNum();i++){
            HSSFRow row= sheet.getRow(i);
            if(!ExcelUtil.isBlankRow(row)){
                Person person=getPersonExcelRow(row);//获得一行的值
                list.add(person);   
            }
        }
        return list;
    }
    /**
     * 获取Excel的一行数值
     * set Supplier
     * @param row
     * @return
     * @throws Exception
     */
    public static Person getPersonExcelRow(Row row) throws Exception{
        Person p=new Person();
        p.setName(row.getCell(1).toString().trim().replaceAll(ConfigConstants.CN_SPACE,"").trim());
        p.setSex(row.getCell(2).toString().trim().replaceAll(ConfigConstants.CN_SPACE,"").trim());//性别为汉字
        p.setIdcard(row.getCell(3).toString().trim().replaceAll(ConfigConstants.CN_SPACE,"").trim());
                p.setApplyUnit(row.getCell(4).toString().trim().replaceAll(ConfigConstants.CN_SPACE,"").trim());
        p.setRemark(row.getCell(5).toString().trim().replaceAll(ConfigConstants.CN_SPACE,"").trim());//培训日期设为备注
            p.setLicenseNumber(row.getCell(6).toString().trim().replaceAll(ConfigConstants.CN_SPACE,"").trim());//【年龄不足】【超龄】后面处理

        //System.out.println("p:"+p);

        return p;

    }

这样写在数据量不是很大的情况下,实现功能是没有问题的,但就是代码不简洁,业务整体流程不顺畅。
又比如:

    //=====================common check======================//
    /**
     * XXX 通用 接口验证
     * 
     * @param type
     * @param workSheet
     * @param requiredXml
     * @param notNullXml
     * @return
     */
    private String commonCheck(int type,Wms2ItosWorkSheet workSheet,
            String[] requiredXml,String[] notNullXml){
        System.out.println("workSheet.opDetail:"+workSheet.getOpDetail());
        //=============验证workSheet 非空验证===============//
        callResult=OpDetailUtil.validateWorkSheet(workSheet);
        if(!VALID_SUCCESS.equals(callResult)){
            return callResult;
        }
        //=============验证xml SAX解析===============//
        callResult=OpDetailUtil.checkXmlByOpDetail(workSheet.getOpDetail());
        if(!VALID_SUCCESS.equals(callResult)){
            return callResult;
        }

        //=============解析xml===============//
        rowList=OpDetailUtil.getRowListByOpDetail(workSheet.getOpDetail());
        nodeList=OpDetailUtil.getNodeListByRowList(rowList);

        //=============验证rowList,nodeList 所有节点,重复字段===========//
        callResult=OpDetailUtil.checkRowList(nodeList,requiredXml);
        if(!VALID_SUCCESS.equals(callResult)){
            return callResult;
        }

        //=============解析rowList===============//
        eleMap=OpDetailUtil.getElementMapByRowList(rowList);

        //=============验证eleMap 必填字段================//
        callResult=OpDetailUtil.checkElementMap(eleMap, notNullXml);
        if(!VALID_SUCCESS.equals(callResult)){
            return callResult;
        }

        //callResult为0,则执行 业务验证
        switch(type){

            //1.新单分派+CL
            case WebserviceConstants.NEW_WORK_SHEET_CL: 
                callResult = ComplainsValidation.validateNewWorkSheetCL(workSheet, eleMap);
                break;

            //2.审核时间    
            case WebserviceConstants.NEW_WORK_SHEET_SH: 
                callResult = ComplainsValidation.validateNewWorkSheetSH(workSheet, eleMap);
                break;

            //3.回复时间
            case WebserviceConstants.NEW_WORK_SHEET_HF: 
                callResult = ComplainsValidation.validateNewWorkSheetHF(workSheet, eleMap);
                break;

            //4.催单
            case WebserviceConstants.NOTIFY_WORK_SHEET_REMIND: 
                callResult = ComplainsValidation.validateRemind(workSheet, eleMap);
                break;

            //5.备注
            case WebserviceConstants.NOTIFY_WORK_SHEET_REMARK:
                callResult = ComplainsValidation.validateRemark(workSheet, eleMap);
                break;

            //6.协同回复
            case WebserviceConstants.REPLY_WORK_SHEET_XT:
                callResult = ComplainsValidation.validateXTReply2(workSheet, eleMap);
                //用第二套规则
                break;

            //7.回复(协同单、SS单)
            case WebserviceConstants.REPLY_WORK_SHEET:
                callResult = ComplainsValidation.validateReply(workSheet, eleMap);
                break;

            //8.归档
            case WebserviceConstants.CHECKIN_WORK_SHEET: 
                callResult = ComplainsValidation.validateCheckin(workSheet, eleMap);
                break;

            default:callResult = "none";
                break;

        }

        return callResult;
    }

这是一个webservice对外发布接口的通用验证,接收的是14个字段和一段xml格式的remark。暂且不管代码结构写的好坏,其中
验证xml SAX解析解析xml基本上是相同的代码:

//================= 对xml的验证 =================//
/**
     * 增加对BOM(<?xml version="1.0" encoding="utf-8"?>)的判断
     * 
     * 检验SAX是否可以解析opDetail
     * 
     * 1.首先,XML解析器根据文件的BOM来解析文件;
     * 2.如果没找到BOM,由用XML里的encoding属性指定的编码;
     * 3.如果xml里encoding没指定的话,就默认用utf-8来解析文档。
     * 4.然后又可以推出,BOM和ENCODING都有的话,则以BOM指定的为准。
     * 
     * @param opDetail
     */
    public static String checkXmlByOpDetail(String opDetail) {

        //解析xml格式
        try {
            Document jDoc = DocumentHelper.parseText(opDetail);
            String encode = jDoc.getXMLEncoding();

            if(StringUtil.isEmpty(encode)||"UTF-8".equalsIgnoreCase(encode)||"utf-8".equals(encode)){
                //可以解析
            }else{
                return "opDetail的xml格式须为UTF-8";
            }
            //dom4j可以解析非utf-8格式的xml
//          List<Element> l = jDoc.selectNodes("//opDetail/recordInfo/fieldInfo");
//          System.out.println("==================l:"+l.size());
//          for(Element e:l){
//              System.out.println(e.elementText("fieldEnName"));
//          }


        } catch (DocumentException e1) {
            e1.printStackTrace();
            return e1.getNestedException().toString();
        } 

        //验证sax解析
        SAXReader saxReader = new SAXReader();
        try {
            //生成文档对应实体 
            Document saxDoc = saxReader.read(new ByteArrayInputStream(opDetail.getBytes("UTF-8")));
            //获取指定路径下的元素列表,这里指获取所有的data下的row元素  
            saxDoc.selectNodes("//opDetail/recordInfo/fieldInfo");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return e.getMessage().toString();
        } catch (DocumentException e) {
            e.printStackTrace();
            return e.getNestedException().toString();
        } 
        //doc可以正常解析
        return CHECK_SUCCESS;
    }
//==================== 解析xml ======================//
    /**
     * 使用SAX解析opDetail
     * @param opDetail
     */
    @SuppressWarnings("unchecked")
    public static List<Element> getRowListByOpDetail(String opDetail) {

        List<Element> rowList=new ArrayList<Element>();

        SAXReader saxReader = new SAXReader();

        try {
            //生成文档对应实体 
            Document doc = saxReader.read(new ByteArrayInputStream(opDetail.getBytes("UTF-8")));
            //获取指定路径下的元素列表,这里指获取所有的data下的row元素  
            rowList=doc.selectNodes("//opDetail/recordInfo/fieldInfo");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
//          return null;
        } catch (DocumentException e) {
            e.printStackTrace();
//          return null;
        } 
        //rowList可以为空,所以不在公共方法里验证
        return rowList;
    }

如果xml很长或者解析比较慢,一个实时性的webservice就会造成不必要的性能开销
在lcms中,对于接口过来的数据验证,全部通过异常的方式返回(定时任务运行接口程序)。

    /**
     * 
     * <p>
     * Description: 任务执行
     * </p>
     * 
     * @param ctx ctx
     */
    protected void work(JobExecutionContext ctx) {

        this.thread = Thread.currentThread();
        this.logger.info("=============== 定时任务处理开始   ====  " + this.dateFormat.format(new Date()));

        try {
            //默认成功
            this.taskLog.setConsequence(Constants.TASK_RESULT_SUCCEED);
            //抽象方法,具体任务的执行
            doExcute(ctx);

        } catch (Exception e) { //此处允许捕获Exception异常 byLiao
            //其他异常
            this.logger.error("", e);
            this.taskLog.setConsequence(Constants.TASK_RESULT_FAILED);
            //失败原因说明
            this.taskLog.setConsequenceDesc(GetExceptionInfo.getStackTrace(e));
        } finally {
            this.logger.info("task status :" + this.taskLog.getConsequence());
        }

        this.logger.info("=============== 定时任务处理结束   ====  " + this.dateFormat.format(new Date()));

    }
  • 框架级别异常处理
    SpringMVC异常,在baseController中,使用基于@ExceptionHandler异常处理
 /**
     * 
     * <p>
     * Description: 基于@ExceptionHandler异常处理
     * </p>
     * 
     * @param request 请求
     * @param response 响应
     * @param ex ex
     * @return errorMessage
     */
    @ExceptionHandler
    public String exp(HttpServletRequest request, HttpServletResponse response, Exception ex) {

        logger.error(ex, ex);

        request.setAttribute("ex", ex);

        //如果是json格式的ajax请求
        if (request.getHeader("accept").indexOf("application/json") > -1
                || (request.getHeader("X-Requested-With") != null 
                    && request.getHeader("X-Requested-With")
                    .indexOf("XMLHttpRequest") > -1)) {

            return ajaxExceptionHandle(request, response, ex);

        } else {
            //普通请求
            //根据生成环境和开发环境,分别指向不同的异常处理页面
            //生产环境--不对外暴露异常信息:根据服务器host判断
            String host;
            host = getHost(request);

            if (host.equalsIgnoreCase(LOCAL_HOST) || host.equalsIgnoreCase(LOCAL_HOST2)) {
                //debug--开发环境可见
                return "exception/debugError"; 
            } else {
                //生产环境--请联系管理员
                return "exception/productError";
            }
        }
    }

    /**
     * <p>
     * Description: ajax异常处理
     * </p>
     * 
     * @param request req
     * @param response rep
     * @param ex ex
     * 
     * @return Str
     */
    public String ajaxExceptionHandle(HttpServletRequest request, HttpServletResponse response, Exception ex) {

        //如果是json格式的ajax请求
        //        response.setStatus(STATE_INNER_SERVER_ERROR);
        //        response.setContentType("application/json;charset=utf-8");
        //        try {
        //            PrintWriter writer;
        //            writer = response.getWriter();
        //            writer.write(ex.getMessage());
        //            writer.flush();
        //        } catch (IOException ioe) {
        //            logger.error(ioe);
        //        }
        //        return null;
        return "exception/ajaxError";
    }

另外,在Struts2中,定义了全局异常和全局返回结果来处理异常

<global-results>
            <result name="appBaseError">/pages/common/appBaseError.jsp</result>
            <result name="runtimeError">/pages/common/runtimeError.jsp</result>
            <result name="unkownError">/pages/common/runtimeError.jsp</result>
            <result name="timeOut">/pages/common/timeOut.jsp</result>
            <result name="input">/pages/common/input.jsp</result>
        </global-results>

        <global-exception-mappings>      
            <exception-mapping result="appBaseError" exception="com.broadtext.framework.exception.BaseException"></exception-mapping>
            <exception-mapping result="runtimeError" exception="com.broadtext.framework.exception.CrashException"></exception-mapping> 
            <exception-mapping result="unkownError" exception="java.lang.Exception"></exception-mapping>     
        </global-exception-mappings>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值