自己的Java規範文件

冰魄秋雨發表於2018-12-16
  1. 參考阿里Java規範文件

  2. 不建議使用過時方法
  3. 泛型需要加上<>,這種方式建立的物件是不推薦的。

Map object = new HashMap();//禁止使用
  1. 字串比較時,不需要大小寫時,使用equalsIgnore方法,不使用toUppers方法
str.equals(string.toUppers());//不推薦使用
str.equalsIgnore(string);//推薦使用
  1. Integer很多時候沒有必須要.intValue()方法,在使用Intger或者int時,不需要使用Integer,valueof(i)進行強制轉化,java內部會進行自動拆箱和裝箱
Integer.parseInt(str); //推薦使用
Integer,valueof(str);//不推薦使用
  1. 儘量使用StringBuilder來替換StringBuffer,在使用執行緒的時候除外。

  2. logger方式內部不建議用+進行拼接,而使用字串中帶{}的方式,也不需要進行isDebug的方式進行判斷,在使用{}語法之後,JVM執行到這時不會進行字串拼接,logger會自動進行識別某個日誌級別是否開啟。使用log4j2

logger.info("{}",str);
  1. 使用了StringBuilder之後,就不需要使用+在繼續拼接了。
StringBuilder builder = new StringBuilder();
builder.append("hello" + kitty); //禁止使用
builder.append("hello").append("kitty");//推薦使用
  1. 程式必須要異常攔截,方法內部處理異常,必須要列印異常日誌
try{
      
  }catch(Exception e){
      //什麼都不做      // 不推薦
      logger.error("{}",e);//推薦異常日誌列印出來
  }
  1. Spring攔截,統一處理空格(需要封裝request)
@Configuration
public class HttpFilter implements Filter {

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {

  }

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                       FilterChain filterChain) throws IOException, ServletException {
    WebServletRequestWrapper wrapperRequest = null;
    if (servletRequest instanceof HttpServletRequest) {
      wrapperRequest = new WebServletRequestWrapper((HttpServletRequest) servletRequest);
    }
    if (wrapperRequest == null) {
      filterChain.doFilter(servletRequest, servletResponse);
    } else {
      filterChain.doFilter(wrapperRequest, servletResponse);
    }
  }

  @Override
  public void destroy() {

  }
}

public class WebServletRequestWrapper extends HttpServletRequestWrapper {

  private Map<String, String[]> params = new HashMap<String, String[]>();

  private final String body;

  public WebServletRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    body = inputStreamBody(request);
    //處理引數
    Map<String, String[]> parameterMap = request.getParameterMap();
    this.params.putAll(parameterMap);
    this.modifyParameterValues();

  }

  @Override
  public ServletInputStream getInputStream() throws IOException {
    //將input流封裝一次
    final ByteArrayInputStream byteArrayInputStream =
        new ByteArrayInputStream(body.getBytes("utf-8"));
    DelegatingServletInputStream delegatingServletInputStream = new DelegatingServletInputStream(
        byteArrayInputStream);
    //非json型別,直接返回
    if (!super.getHeader(HttpHeaders.CONTENT_TYPE)
        .equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {
      return delegatingServletInputStream;
    }
    //為空,直接返回
    if (StringUtils.isEmpty(body)) {
      return delegatingServletInputStream;
    }
    Map<String, String> map = new HashMap<>();
    json2Map(map, body);
    return new DelegatingServletInputStream(
        new ByteArrayInputStream(JSON.toJSONString(map).getBytes("utf-8")));
  }

  @Override
  public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream(), "UTF-8"));
  }


  public String getBody() {
    return this.body;
  }

  /**
   * 將parameter的值去除空格後重寫回去
   */
  public void modifyParameterValues() {
    Iterator<Entry<String, String[]>> it = params.entrySet().iterator();
    while (it.hasNext()) {
      Entry<String, String[]> entry = it.next();
      String key = entry.getKey();
      String[] values = entry.getValue();
      values[0] = values[0].trim();
      params.put(key, values);
    }
  }

  /**
   * 重寫getParameter 引數從當前類中的map獲取
   */
  @Override
  public String getParameter(String name) {
    String[] values = params.get(name);
    if (values == null || values.length == 0) {
      return null;
    }
    return values[0];
  }

  @Override
  public String[] getParameterValues(String name) {//同上
    return params.get(name);
  }

  @Override
  public Map<String, String[]> getParameterMap() {
    return this.params;
  }

  /**
   * 轉化body
   */
  public String inputStreamBody(HttpServletRequest request) throws IOException {
    StringBuffer stringBuilder = new StringBuffer();
    BufferedReader bufferedReader = null;
    try {
      InputStream inputStream = request.getInputStream();
      if (inputStream != null) {
        bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
        char[] charBuffer = new char[128];
        int bytesRead = -1;
        while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
          stringBuilder.append(charBuffer, 0, bytesRead);
        }
      } else {
        stringBuilder.append("");
      }
    } catch (IOException ex) {
      throw ex;
    } finally {
      if (bufferedReader != null) {
        try {
          bufferedReader.close();
        } catch (IOException ex) {
          throw ex;
        }
      }
    }
    return stringBuilder.toString();
  }

  /**
   * 將json字串轉化為Map,並去除掉值的空格
   */
  public static void json2Map(Map<String, String> map, String json) {
    JSONObject object = JSONObject.parseObject(json);
    Set set = object.keySet();
    for (Object o : set) {
      String key = (String) o;
      String s = object.getString(key);
      if (s.indexOf(`{`) == 0 && s.lastIndexOf(`}`) == s.length() - 1) {//物件.
        JSONObject oo = fromObject(s);
        if (oo == null) {
          map.put(key, s.trim());
        } else {
          json2Map(map, s);
        }
      } else {
        map.put(key, s.trim());
      }
    }
  }

  /**
   * 將json字串轉化為JSONObject,異常返回null
   */
  public static JSONObject fromObject(String jsonStr) {
    return JSONObject.parseObject(jsonStr);
  }
}
  1. 每個web請求輸入和輸出列印(Spring 切面)
@Aspect
@Component(value = "lmsControllerInterceptor")
public class ControllerInterceptor {

  private static final Logger logger = LoggerFactory.getLogger(ControllerInterceptor.class);

  @Pointcut("execution(* com.cootf.resim.lms.web.controller.*..*(..))")
  public void methodPointcut() {

  }

  @AfterThrowing(pointcut = "methodPointcut()", throwing = "e")
  public void doThrowingAfterMethodPointcut(JoinPoint jp, Throwable e) {
    logger.error("exception: {}", MiscUtil.trace(e));
  }

  @SuppressWarnings("unchecked")
  @Around("methodPointcut()")
  public Object aroundMethodPointcut(ProceedingJoinPoint pjp) {
    Object result = null;
    long startTime = System.currentTimeMillis();
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
      .getRequestAttributes();
    if (attributes == null) {
      return result;
    }
    WebServletRequestWrapper request = (WebServletRequestWrapper) attributes.getRequest();//封裝了流
    String method = request.getMethod();
    String uri = request.getRequestURI();
    long endTime;
    //獲取引數
    Map<String, String> paramMap = new HashMap<>();
    Enumeration<String> paramNames = request.getParameterNames();
    while (paramNames.hasMoreElements()) {
      String paramName = paramNames.nextElement();
      String valueStr = request.getParameter(paramName);
      paramMap.put(paramName, valueStr);
    }
    logger.info("request start,uri: {},method: {},req: {},body:{}", uri, method, paramMap,
      request.getBody().replaceAll("\r|\n", ""));
    try {
      result = pjp.proceed();
      endTime = System.currentTimeMillis();
      logger.info("request end,elap: {}ms,uri: {},method: {},rsp: {}", (endTime - startTime), uri,
        method, MiscUtil.obj2Json(result));

    } catch (Throwable throwable) {
      endTime = System.currentTimeMillis();
      logger
        .error("request end,elap: {}ms,uri: {},method: {},e: {}", (endTime - startTime),
          uri, method, MiscUtil.trace(throwable));
      return Rsp.transEnd(RpcFailReasonEnum.ERR_SYSTEM_ERROR.getCode(),
        RpcFailReasonEnum.ERR_SYSTEM_ERROR.getDesc());
    }
    return result;
  }
}
  1. 引數需要校驗, 使用Hibernate-validate框架,每個請求都建立實體,註解式的引數校驗。
  2. 出現兩次以上的程式碼塊需要抽離單獨的方法。
  3. idea中置灰的程式碼刪除
  4. resutful風格的路徑,都必須要小寫
@PostMapping("/device/new") // 新增裝置介面
  1. 每個介面或方法(介面的實現除外)都需要有一個簡短的中文註釋
 /**
   * 通過電話號碼查詢使用者
   */
  Custom selectCustom(String phoneNumber);
  1. 不同層的方法開頭規則
  • DAO層 方法以select開頭。 selectUserInfo(); insert,update,delete(即mysql使用的關鍵詞)
  • Service和Controller層方法queryUserInfo(),saveUserInfo(),editUserInfo(),deleteUserInfo()
  • 資料庫對映實體 字尾entity UserEntity
  • controller 返回實體字尾Rsp UserRsp
  • 引數校驗實體 UserVo
  1. 部署需要寫指令碼,或者是利用框架,實現自動化
  2. 狀態等型別必須使用列舉型別或者是單獨一個類的實體的靜態變數
public enum UserEnum{
    
    ENABLE(0,"啟用"),
    DISABLE(1,"禁止");
    private int code;
    private String desc;
    UserEnum(int code,String desc){
        this.code = code;
        this.desc = desc;
    }    
    public int getCode(){
        return this.code;
    }
    public String desc(){
        return this.desc;
    }
}

public class Constant{
    public static final int ENABLE = 0;//啟用
    public static final int DISABLE = 1;//禁止
    ···
}
  1. if 巢狀不能超過三層,多使用if(){return;}
if(引數不正確){
    return "返回引數不正確";
}
if(使用者沒有找到){
    return "使用者沒有找到";
}

這個是自己最近總結的Java規範文件,在看別人程式碼並且對照自己編碼習慣,總結以上幾點。 以上有幾點是關於web程式的建議。
程式碼一定要規範起來,這樣自己再看自己的程式碼時,就可以形成一個固定的格式,很容易就能夠理解,其他人在看自己的程式碼時,也能夠清晰。寫程式碼不僅僅讓自己能夠看得懂,而且還能夠讓其他人看的懂,需要有一個良好的編碼習慣。

相關文章