相信你們對代碼質量規範已經不陌生,通常大公司都會進行代碼質量檢查,用來管理N多項目的質量,若是達不到要求,那麼很差意思,請去搞搞代碼,從今日後就成爲領導重點管理對象。
在質量管理當中,我負責去管理整個團隊的CQM問題,由此走上代碼規範的道路。
從管理手段來說,開個會,提醒你們要按照公司的規範,根據工具(SonarLint等),提交代碼前,用工具check一下,有問題及時修改。宣傳後你們的反響不大,並且問題愈來愈多,你們明顯不自覺,
都認爲這個沒什麼用啦,浪費時間,不造成習慣。你們都知道,不造成習慣的規範,就像制度擺在這裏木有人執行,可悲的管理者。
對於我來講,也以爲很難執行,有時候我只能呵呵一下,但仍是要想辦法管理起來,由此想經過可視化界面展示起來,讓全部都看到,CQM問題不控制,會愈來愈多的不規範代碼橫空出世,下面講講如何
創建CQM可視化界面,
一、思考Sonar的結果如何才能獲取到?
Sonar編譯後,會記錄歷史記錄,Sonar提供http訪問接口,返回json報文格式,可獲取到你想要的結果,這下有點小興奮,有渠道獲取了。
訪問URL:http://ip:port/api/resources?resource=${project_key}&&metrics=${metrics_key}
返回格式:[{"id":793214,"uuid":"1234","key":"com.myjob","name":"CRM_JOB","scope":"PRJ","qualifier":"TRK","date":"2016-11-25T19:18:35+0800","creationDate":"2016-04-25T10:26:12+0800","lname":"CRM_JOB","version":"1.0","description":"","msr":[{"key":"critical_violations","val":0.0,"frmt_val":"0"}]}]
開始編碼:
public Map reqeustIde(String resource, String metrics){
final HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setConnectionTimeout(AbstractQuery.DEFAULT_TIMEOUT_MILLISECONDS);
params.setSoTimeout(AbstractQuery.DEFAULT_TIMEOUT_MILLISECONDS);
params.setDefaultMaxConnectionsPerHost(4);
params.setMaxTotalConnections(40);html
final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.setParams(params);
HttpClient httpClient = new HttpClient(connectionManager);
httpClient.getParams().setAuthenticationPreemptive(true);
Credentials defaultcreds = new UsernamePasswordCredentials("abcdefg", "123456");
httpClient.getState().setCredentials(AuthScope.ANY, defaultcreds);
final PostMethod post = new PostMethod("http://localhost:8080/api/resources?resource=" + resource + "&metrics=" + metrics);
try {
httpClient.executeMethod(post);
String jsonStr = post.getResponseBodyAsString();
System.out.println(jsonStr);
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(jsonStr.substring(1, jsonStr.length() - 1), Map.class);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new HashMap();
}
二、如何把這些信息轉換成模型呢?
模型考慮維度:
①編譯的分支項目,就是要掃描的編譯項目
②掃描的issuess類型
③掃描Sonar後的結果記錄,定時掃描,若是已經掃描過就不記錄
④分支項目的臨界值,保證這個值不能被超過,若是超過則告警
通過我慎重思考,產出一下模型:
create table tb_project(
id bigint UNSIGNED not null auto_increment comment '主鍵標識',
project_name varchar(100) not null default '' comment '編譯項目名稱',
project_key varchar(100) not null default '' comment '項目key',
create_time timestamp NOT NULL DEFAULT '1980-01-01 00:00:00' COMMENT '記錄建立時間',
last_update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '記錄最後修改時間',
PRIMARY KEY (`id`)
);java
create table tb_type(
id bigint UNSIGNED not null auto_increment comment '主鍵標識',
type_name varchar(100) not null default '' comment '掃描類型中文名稱',
type_key varchar(100) not null default '' comment '掃描key',
create_time timestamp NOT NULL DEFAULT '1980-01-01 00:00:00' COMMENT '記錄建立時間',
last_update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '記錄最後修改時間',
PRIMARY KEY (`id`)
);json
create table tb_scan_critical_value(
id bigint UNSIGNED not null auto_increment comment '主鍵標識',
project_key varchar(100) not null default '' comment '項目key',
type_key varchar(100) not null default '' comment '掃描key',
critical_val bigint(20) not null default 0 comment '臨界值',
current_val bigint(20) not null default 0 comment '當前值',
create_time timestamp NOT NULL DEFAULT '1980-01-01 00:00:00' COMMENT '記錄建立時間',
last_update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '記錄最後修改時間',
PRIMARY KEY (`id`)
);api
create table tb_scan_record(
id bigint UNSIGNED not null auto_increment comment '主鍵標識',
project_name varchar(100) not null default '' comment '編譯項目名稱',
project_key varchar(100) not null default '' comment '項目key',
uuid varchar(100) not null default '' comment '項目uuid',
version varchar(100) not null default '' comment '版本號,以時間維度',
key_date varchar(50) not null default '' comment '',
key_creationdate varchar(50) not null default '' comment '',
lname varchar(100) not null default '' comment '',
description varchar(200) not null default '' comment '描述',
type_key varchar(100) not null default '' comment '掃描key',
type_val bigint(20) not null default 0 comment '掃描值',
PRIMARY KEY (`id`)
);
三、action請求處理邏輯思考
有如下步驟:
①查詢須要掃描的內容
select a.project_key,b.type_key from tb_project a , tb_type b
②查出重複的信息
select distinct project_key,version from tb_scan_record where project_key ='${project_key}' and version ='${version}'
③把掃描結果插入到結果表中:tb_scan_record
④:插入臨界值表:tb_scan_critical_value,若是已經存在則更新critical_val、current_val值,若是critical_val>current_val,則臨界值之後以current_val爲準,這裏控制會愈來愈小。
⑤統計結果輸出
select project_name,project_key,sum(critical_val) as total_critical_val,sum(current_val) as total_current_val from (
select a.project_name,b.project_key,b.critical_val,b.current_val
from tb_project a,tb_scan_critical_value b where a.project_key = b.project_key order by a.project_key) c group by project_name,project_key
⑥查詢類型的輸出:
select a.project_name,b.project_key,b.critical_val as critical_val,b.type_key,b.current_val as current_val from tb_project a,tb_scan_critical_value b where a.project_key = b.project_key order by project_key
四、編寫圖形界面app
Jsp頁面:
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CQM可視化界面</title>
<script language="JavaScript">
function myrefresh()
{
window.location.reload();
}
setTimeout('myrefresh()',60000 * 10 ); //指定1秒刷新一次
</script>
</head>
<body>
<table cellpadding="1" cellspacing="0" width="100%" style="border-width: 1px;font-size:55px;" >
<tr align="center">
<td>CQM可視化界面</td>
</tr>
</table>
<table cellpadding="1" cellspacing="0" width="100%" style="border-width: 1px;font-size:55px;" >
<c:forEach items="${totalPageMap}" var="totalObj">
<tr>
<c:if test="${totalObj.status== 'fail'}">
<td style="background-color: red">
${totalObj.project_name}【臨界值:${totalObj.total_critical_val}當前值:${totalObj.total_current_val}】
</td>
</c:if>
<c:if test="${totalObj.status== 'succeed'}">
<td style="background-color: green">
${totalObj.project_name}【臨界值:${totalObj.total_critical_val}當前值:${totalObj.total_current_val}】
</td>
</c:if>
</tr>
</c:forEach>
</table>
<table cellpadding="1" cellspacing="0" width="100%" style="border-width: 1px;font-size:18px;" >
<tr style="background-color: green">
<td>項目</td>
<td>等級類型</td>
<td>臨界值</td>
<td>當前值</td>
</tr>
<c:forEach items="${pageMap}" var="obj">
<c:if test="${obj.status == 'fail'}">
<tr style="background-color: red">
<td >
${obj.project_name}
</td>
<td >
${obj.type_key}
</td>
<td >
${obj.critical_val}
</td>
<td >
${obj.current_val}
</td>
</tr>
</c:if>
<c:if test="${obj.status== 'succeed'}">
<tr style="background-color: green">
<td >
${obj.project_name}
</td>
<td >
${obj.type_key}
</td>
<td >
${obj.critical_val}
</td>
<td >
${obj.current_val}
</td>
</tr>
</c:if>
</c:forEach>
</table>
</body>
</html>
做者:godsferjsp