前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、异常相关

1.1、异常类

1.1.1、业务异常类:BusinessException

package com.healerjean.proj.exception;


import com.healerjean.proj.enums.ResponseEnum;


public class BusinessException extends RuntimeException {

    private int code;

    public BusinessException(int code) {
        this.code = code;
    }

    public BusinessException(String message) {
        super(message);
        this.code = ResponseEnum.逻辑错误.code;
    }

    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(ResponseEnum responseEnum) {
        super(responseEnum.msg);
        this.code = responseEnum.code ;
    }

    public BusinessException(ResponseEnum responseEnum,String message) {
        super(message);
        this.code = responseEnum.code ;
    }

    public BusinessException(String message, Throwable cause) {
        super(message, cause);
        this.code = ResponseEnum.逻辑错误.code;
    }

    public BusinessException(int code ,Throwable e) {
        super(e);
        this.code = code;
    }

    public BusinessException(ResponseEnum responseEnum, Throwable t) {
        super(responseEnum.msg, t);
        this.code = responseEnum.code;
    }


    public void setCode(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

}

1.1.2、参数异常类:ParameterErrorException

package com.healerjean.proj.exception;

import com.healerjean.proj.enums.ResponseEnum;


public class ParameterErrorException extends com.healerjean.proj.exception.BusinessException {

    public ParameterErrorException() {
        super(ResponseEnum.参数错误);
    }

    public ParameterErrorException(ResponseEnum responseEnum) {
        super(ResponseEnum.参数错误, responseEnum.msg);
    }

    public ParameterErrorException(String msg) {
        super(ResponseEnum.参数错误, msg);
    }

}

1.1.3、接口异常类:HaoDanKuApiException

package com.healerjean.proj.exception;

import com.healerjean.proj.enums.ResponseEnum;


public class HaoDanKuApiException extends BusinessException {


    public HaoDanKuApiException(String msg) {
        super(ResponseEnum.好单库接口返回报错, msg);
    }


    public HaoDanKuApiException(Throwable e) {
        super(ResponseEnum.好单库接口请求异常, e);
    }

}

1.1.4、NotFoundException、ExistException

public class ExistException extends BusinessException {

    public ExistException(ResponseEnum  responseEnum) {
        super(responseEnum);
    }

}


public class NotFoundException extends BusinessException {

    public NotFoundException(ResponseEnum  responseEnum) {
        super(responseEnum);
    }

}

1.2、异常全局处理

1.2.1、ControllerHandleConfig

package com.healerjean.proj.config;

import com.healerjean.proj.dto.ResponseBean;
import com.healerjean.proj.enums.ResponseEnum;
import com.healerjean.proj.exception.BusinessException;
import com.healerjean.proj.exception.ParameterErrorException;
import com.healerjean.proj.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletResponse;
import javax.validation.UnexpectedTypeException;
import java.util.HashMap;
import java.util.Map;


@Slf4j
@ControllerAdvice
public class ControllerHandleConfig {

    /**
     * 不支持的请求方始
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(value = HttpStatus.METHOD_NOT_ALLOWED)
    public ResponseBean methodNotSupportExceptionHandler(HttpRequestMethodNotSupportedException e) {
        log.error("不支持的请求方式", e);
        return ResponseBean.buildFailure(ResponseEnum.不支持的请求方式.code, e.getMessage());
    }


    /**
     * 参数类型错误
     * 1、(BindException : 比如 Integer 传入String  )
     * Field error in object 'demoDTO' on field 'age': rejected value [fasdf]; codes [typeMismatch.demoDTO.age,typeMismatch.age,typeMismatch.java.lang.Integer,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [demoDTO.age,age]; arguments []; default message [age]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'age'; nested exception is java.lang.NumberFormatException: For input string: "fasdf"]
     */
    @ExceptionHandler(value = {BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseBean bindExceptionHandler(BindException e) {
        log.error("====参数类型错误===", e);
        return ResponseBean.buildFailure(ResponseEnum.参数类型错误.code, e.getMessage());
    }


    /**
     * 参数格式问题
     */
    @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, HttpMessageConversionException.class, UnexpectedTypeException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseBean httpMessageConversionExceptionHandler(Exception e) {
        log.error("====参数格式异常===", e);
        return ResponseBean.buildFailure(ResponseEnum.参数格式异常.code, e.getMessage());
    }



    /**
     * 参数错误
     */
    @ExceptionHandler(value = ParameterErrorException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseBean parameterErrorExceptionHandler(ParameterErrorException e) {
        log.error("参数异常------------参数错误:code:{},message:{}", e.getCode(), e.getMessage());
        return ResponseBean.buildFailure(e.getCode(), e.getMessage());
    }


    /**
     * 业务异常,给前台返回异常数据
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseBean businessExceptionHandler(BusinessException e) {
        log.error("业务异常------------异常信息:code:{},message{}" ,e.getCode(), e.getMessage());
        return ResponseBean.buildFailure(e.getCode(),e.getMessage());
    }




    /**
     * 所有异常报错
     */
    @ExceptionHandler
    @ResponseBody
    public HttpEntity<ResponseBean> allExceptionHandler(HttpServletResponse response, Exception e) {
        log.error("====系统错误===", e);
        response.setStatus(ResponseEnum.系统错误.code);
        return returnMessage(ResponseBean.buildFailure(ResponseEnum.系统错误));
    }

    private HttpEntity<ResponseBean> returnMessage(ResponseBean responseBean) {
        HttpHeaders header = new HttpHeaders();
        header.add("Content-Type", "application/json");
        header.add("Charset", "UTF-8");
        return new HttpEntity<>(responseBean, header);
    }



    /**
     * 参数非法
     * 1、(BindException : 比如 Integer 传入abc  )
     */
    // @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, HttpRequestMethodNotSupportedException.class, HttpMessageConversionException.class, BindException.class, UnexpectedTypeException.class})
    // @ResponseBody
    // public HttpEntity<ResponseBean> httpMessageConversionExceptionHandler(HttpServletResponse response, Exception e) {
    //     log.error("====参数格式异常===", e);
    //     // 等同于 @ResponseStatus(HttpStatus.BAD_REQUEST)
    //     // 但是setStatus 不能比随便设置,最好一般情况下不要和HttpStatus 有重复的,这样有可能会造成没有输出Response body
    //     response.setStatus(ResponseEnum.参数格式异常.code);
    //     return returnMessage(ResponseBean.buildFailure(ResponseEnum.参数格式异常));
    // }
    // @ExceptionHandler(value ={HttpMessageConversionException.class, BindException.class} )
    // @ResponseBody
    // public HttpEntity<ResponseBean> httpMessageConversionExceptionHandler(Exception e) {
    //     log.error("====参数格式异常===", e);
    //     return new ResponseEntity<>(ResponseBean.buildFailure(ResponseEnum.参数格式异常),HttpStatus.BAD_REQUEST);
    // }

}

2、枚举

2.1、响应枚举

package com.healerjean.proj.enums;

import java.util.Arrays;
import java.util.List;


public enum ResponseEnum {


    正常(200, "访问正常"),

    参数错误(301, "参数错误"),
    参数格式异常(302, "参数格式异常"),
    不支持的请求方式(303, "不支持的请求方式"),
    参数类型错误(304, "参数类型错误"),
    逻辑错误(305, "逻辑错误"),
    未登陆(306, "未登陆"),
    登陆成功(307, "登陆成功"),
    重复操作(308, "重复操作"),
    非法操作(309, "非法操作"),

    请求无法被服务器理解(400, "请求无法被服务器理解"),
    未授权(401, "未授权"),
    访问禁止(403, "访问禁止"),
    页面丢失(404, "页面丢失"),
    系统错误(500, "系统错误"),
    未知错误(999, "未知错误"),


    用户已经存在(1000, "用户已经存在"),
    用户不存在(1001, "用户不存在"),

    微信接口请求异常(2001,"微信接口请求异常"),
    淘宝接口请求异常(2002,"淘宝接口请求异常"),
    淘宝接口数据异常(2003,"淘宝接口数据异常"),
    好单库口请求异常(2004,"好单库口请求异常"),
    好单库接口数据异常(2005,"好单库接口数据异常"),

    ;


    public int code;
    public String msg;


    ResponseEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }


    public static boolean checkExist( Integer code){
        for (ResponseEnum value : ResponseEnum.values()){
            if (value.code == code){
                return true;
            }
        }
        return false;
    }


    public static ResponseEnum toEnum(int code){
        for (ResponseEnum value : ResponseEnum.values()){
            if (value.code == code){
                return value;
            }
        }
        return ResponseEnum.未知错误;
    }

    public static String getMsg(int code){
        for (ResponseEnum value : ResponseEnum.values()){
            if (value.code == code){
                return value.msg;
            }
        }
        return ResponseEnum.未知错误.msg;
    }


    public ResponseEnum value(String enumName){
        return valueOf( enumName ) ;
    }

    public static List<ResponseEnum> getList(){
        return Arrays.asList(values());
    }


}

2.2、业务枚举

package com.healerjean.proj.enums;

public interface BusinessEnum {


    /**
     * 验证码枚举
     */
    enum VerifyCodeTypeEnum {

        图片验证码("captcha", "图片验证码"),
        注册邮箱验证码("RegistEmail", "注册邮箱验证码"),
        找回密码邮箱验证码("RetrievePasswordEmail", "找回密码邮箱验证码"),
        ;

        VerifyCodeTypeEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        public String code;
        public String desc;

        public static VerifyCodeTypeEnum toEnum(String code) {
            for (VerifyCodeTypeEnum item : VerifyCodeTypeEnum.values()) {
                if (item.code.equals(code)) {
                    return item;
                }
            }
            return null;
        }
    }


    /**
     * 模板类型
     */
    enum TemplateTypeEnum {

        邮件("Email", "邮件"),
        ;
        public String code;
        public String desc;

        TemplateTypeEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

    }



    /**
     * 模板名字
     */
    enum TempleNameEnum  {
        邮箱验证("VerifyEmail", "邮箱验证"),
        找回密码邮箱验证("PasswordVerifyEmail", "找回密码邮箱验证"),
        手机号验证("VerifyPhone", "手机号验证"),
        ;
        TempleNameEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        public String code;
        public String desc;


        public static TempleNameEnum toEnum(String code) {
            for (TempleNameEnum item : TempleNameEnum.values()) {
                if (item.code.equals(code)) {
                    return item;
                }
            }
            return null;
        }
    }


    /**
     * 菜单类型
     */
    enum MenuTypeEnum {

        后端菜单("0", "后端菜单"),
        前端菜单("1", "前端菜单");

        MenuTypeEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        public String code;
        public String desc;


        public static MenuTypeEnum toEnum(String code) {
            for (MenuTypeEnum value : MenuTypeEnum.values()) {
                if (value.code .equals( code)) {
                    return value;
                }
            }
            return null;
        }
    }



    /**
     * 用户类型
     */
    enum UserTypeEnum {

        管理人员("manager", "管理人员"),
        网站用户("webuser", "网站用户");

        UserTypeEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }

        public String code;
        public String desc;


        public static MenuTypeEnum toEnum(String code) {
            for (MenuTypeEnum value : MenuTypeEnum.values()) {
                if (value.code .equals( code)) {
                    return value;
                }
            }
            return null;
        }
    }


}


2.3、状态枚举

package com.healerjean.proj.enums;

/**
 * @Description
 * @Author HealerJean
 * @Date 2019-06-16  01:58.
 */
public enum  StatusEnum {

    生效("10", "生效"),
    废弃("99", "废弃");

    StatusEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String code;
    public String desc;


}

2.4、下拉菜单枚举

package com.duodian.admore.data;

import java.io.Serializable;

/**
 * 下拉列表用
 */
public class LabelValueBean implements Serializable{
    private static final long serialVersionUID = -1211726511402154326L;

    private String label;
    private String value;

    private Boolean checked = false;

    public LabelValueBean() {
    }

    public LabelValueBean(String label, String value) {
        this.label = label;
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public Boolean getChecked() {
        return checked;
    }

    public void setChecked(Boolean checked) {
        this.checked = checked;
    }
}

3、响应Bean

package com.healerjean.proj.dto;


import com.healerjean.proj.enums.ResponseEnum;
import com.healerjean.proj.utils.JsonUtils;

/**
 * 返回对象
 */
public class ResponseBean {

    private ResponseBean() {
    }

    public static ResponseBean buildSuccess() {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(true);
        responseBean.setCode(ResponseEnum.正常.code);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }

    public static ResponseBean buildSuccess(String msg) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(true);
        responseBean.setCode(ResponseEnum.正常.code);
        responseBean.setResult(msg);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }

    public static ResponseBean buildSuccess(Object result) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(true);
        responseBean.setCode(ResponseEnum.正常.code);
        responseBean.setResult(result);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }

    public static ResponseBean buildSuccess(String msg, Object result) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(true);
        responseBean.setCode(ResponseEnum.正常.code);
        responseBean.setMsg(msg);
        responseBean.setResult(result);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }

    public static String buildSensitivitySuccess(String msg, Object result) {
        return JsonUtils.toJsonStringWithSensitivity(buildSuccess(msg, result));
    }

    public static String buildSensitivitySuccess(Object result) {
        return JsonUtils.toJsonStringWithSensitivity(buildSuccess(result));
    }


    public static ResponseBean buildFailure() {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(false);
        responseBean.setCode(ResponseEnum.系统错误.code);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }

    public static ResponseBean buildFailure(String msg) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(false);
        responseBean.setCode(ResponseEnum.系统错误.code);
        responseBean.setMsg(msg);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }

    public static ResponseBean buildFailure(ResponseEnum responseEnum) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(false);
        responseBean.setCode(responseEnum.code);
        responseBean.setMsg(responseEnum.msg);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }


    public static ResponseBean buildFailure(int code, String msg) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(false);
        responseBean.setCode(code);
        responseBean.setMsg(msg);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }


    public static ResponseBean buildFailure(ResponseEnum responseEnum, String msg) {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setSuccess(false);
        responseBean.setCode(responseEnum.code);
        responseBean.setMsg(msg);
        responseBean.setDate(System.currentTimeMillis() + "");
        return responseBean;
    }


    private boolean success;
    private Object result = "{}";
    private String msg = "";
    private int code;
    private String date;

    public boolean isSuccess() {
        return success;
    }

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

    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }

    public String getMsg() {
        return msg;
    }

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

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}

4、POJO(BO、DTO、VO、AO)、Query

POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。

VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。

DO(Data Object):此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。

DTO(Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。

BO(Business Object):业务对象,由 Service 层输出的封装业务逻辑的对象。

AO(Application Object):应用对象,在 Web 层与 Service 层之间抽象的复用对象模型,极为贴 近展示层,复用度不高。

Query:数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止使用 Map 类 来传输。

数据对象:xxxDO,xxx即为数据表名。

数据传输对象:xxxDTO,xxx为业务领域相关的名称。

展示对象:xxxVO,xxx一般为网页名称。

4.1、VO( View Object)

显示层对象,通常是Web向模板渲染引擎层传输的对象

public List<UserVO> getUserVOs(UserQuery userQuery){
    
   //DTO转VO
    BeanUils.dtoToUserVO(userservice.getUserDTOs());
}

4.2、DTO (Data Transfer Object)

数据传输对象,Service或Manager向外传输的对象。

 List<UserDTO> getUserDTOs(UserQuery userQuery){
     
      //BO转DTO,也可能DO转DTO
    BeanUils.boToUserDTO(userservice.getUserBOs());
 }

4.3、BO( Business Object):

业务对象。 由Service层输出的封装业务逻辑的对象。

Service内部的私有代码 
List<UserBO> getUserBOs(UserQuery userQuery){

   //DO转VO
    BeanUils.doToUserBO(userdao.getUserDOs());
}

4.4、DO ( Data Object)

与数据库表结构一一对应,通过DAO层向上传输数据源对象。**

List<UserDO> getUsers(UserQuery userQuery);

ContactAuthor