7

我正在为我们的 Java/JSP Web 应用程序(当然是旧版 ;-) 创建一份初步的、广泛的静态代码分析报告,以供管理层提高对质量问题的认识。主要Java代码没有问题,有很多免费工具可用,例如PMD、Checkstyle、Classcycle等。

但是 JSP 呢?我们的 JSP 中嵌入了相当多的 Java 代码(不幸的是),这需要进行分析。我可以使用哪些工具或需要遵循哪些流程来静态分析 JSP?

  • 我知道 PMD 5 涵盖 JSP 的新功能,是否值得探索?
  • 我可以以某种方式生成 JSP 的源 Servlet 并使用基本的 Java 分析工具,如果是这样,那么获取 JSP 的 Java 源的最简单方法是什么?
4

4 回答 4

3

正如 henry 正确指出的那样,JSP 的一个很好的衡量标准是“scriptlet 代码的行数”。这可以通过一些正则表达式来完成。

我发现代码行数与 HTML ( =LoC_Java/LoC_Html) 行数的比率最具表现力:这个数字越小越好。高达 20% 或 30% 的比率看起来不错,但高于 50% 甚至 > 1 的值是不好的。在我的分析中,我发现 JSP 的比率高达 6(非常糟糕)。

页面指​​令的数量也提供了粗略的了解。由于这个数字主要是由进口引起的,数字高表明耦合度高。

类似的指标在具有JSP 规则集的PMD中可用。Is 基于 HTML 页面分析,能够报告 scriptlet 的数量、scriptlet 的长度、重复导入和编码问题以及纯 HTML 反模式。

于 2013-03-23T19:17:34.413 回答
3

一个非常简单的指标可能适用于您的目的 - “此 jsp 是否包含脚本”或“脚本代码行数”,您应该能够将其与 grep 或类似的东西拼凑在一起。

如果您要向管理层推销时间来解决问题,那么除此之外的细节是否会增加任何价值?

- - 编辑 - -

一个快速的谷歌建议你可以使用这个提取我上面为 jsps 建议的统计信息

http://www.semanticdesigns.com/Products/SearchEngine/

在这个问题中被建议作为答案

什么是衡量 JSP 项目规模的好方法?

于 2013-03-14T11:44:54.057 回答
1

我不想听起来很苦涩,但我想摆脱什么?

我认为(我可能错了)在 JSP 上获取代码质量指标并不是真正有用,因为基础实际上是一种非常糟糕的做法。

就个人而言,我会尝试投入任何资源或时间来弄清楚如何将逻辑从 JSP 迁移到 MVC 或 DCI 框架。

于 2013-03-14T10:52:03.727 回答
0

老实说,这个分​​析(如果可能的话)不会给你任何东西。JSP 中的混合代码简直糟透了。如果最初不可能迁移到任何 MVC 框架,唯一的解决方案是至少将这些迁移到服务类中。以后这些服务类可以更容易地重用和分析。

我最近工作的一个痛苦的jsp代码示例:系统已有9年历史

oListCode.setDB(driverclass, databaseurl, databasetype.intValue());
java.util.Vector oVecActiveStatusListCodes = oListCode.getListCodes(13, user.getAdminId());


java.text.DecimalFormat dformat = new java.text.DecimalFormat("###0.00");
java.text.DecimalFormat averageformat = new java.text.DecimalFormat("###0.##");

java.util.Vector userDirectoryVector = new java.util.Vector();

String searchoptionvalue = request.getParameter("iscombinesearch");
if (searchoptionvalue != null && searchoptionvalue.equals("on")) {
    java.util.Vector oVectorStudents = (java.util.Vector) session.getAttribute("studentsearchresult");

    if (oVectorStudents != null) {
        oVector.addAll(oVectorStudents);
    }
}


java.util.Vector<StatusSequenceInfo> oStaSeqVector = student.getStatusSequence(user.getAdminId());
java.util.Vector<StatusSequenceInfo> oEnrollStatusvecto = student.getProgramStatus(user.getAdminId());


String parameterList = "?columns=" + java.net.URLEncoder.encode(columns, "UTF-8") +
                    "&activestatus=" + activestatus +
                    "&studenttype=" + studenttype +
                    "&faith=" + faith +
                    "&race=" + race +
                    "&levelid=" + levelid +
                    "&levelidlist=" + levelidlist +
                    "&curriculumid=" + curriculumid +
                    "&programmeid=" + programmeid +
                    "&programmelevelid=" + programmelevelid +
                    "&semesterid=" + semesterid +
                    "&sex=" + sex +
                    "&idnumber=" + java.net.URLEncoder.encode(idnumber, "UTF-8") +
                    "&batchnumber=" + java.net.URLEncoder.encode(batchnumber, "UTF-8") +
                    "&firstname=" + java.net.URLEncoder.encode(firstname, "UTF-8") +
                    "&middlename=" + java.net.URLEncoder.encode(middlename, "UTF-8") +
                    "&lastname=" + java.net.URLEncoder.encode(lastname, "UTF-8") +
                    "&nationality=" + java.net.URLEncoder.encode(nationality, "UTF-8") +
                    "&address=" + java.net.URLEncoder.encode(address, "UTF-8") +
                    "&city=" + java.net.URLEncoder.encode(city, "UTF-8") +
                    "&state=" + java.net.URLEncoder.encode(state, "UTF-8") +
                    "&zip=" + java.net.URLEncoder.encode(zip, "UTF-8") +
                    "&homephone=" + homephone +
                    "&email=" + email +
                    "&advisor=" + java.net.URLEncoder.encode(advisor, "UTF-8") +
                    "&dob=" + dob +
                    "&visaexpiredate=" + java.net.URLEncoder.encode(visaexpiredate, "UTF-8") +
                    "&regstatus=" + regStatus +
                    "&regstartDate=" + java.net.URLEncoder.encode(regstartDate, "UTF-8") +
                    "&regendDate=" + java.net.URLEncoder.encode(regendDate, "UTF-8") +
                    "&shashmap=" + shashmap +
                    "&studentcount=" + studentcount + extendedurl;

String paginationLink = "admin_search_student_result.jsp" + parameterList;
long totalpage = new Double(Math.ceil(new Double(studentcount).doubleValue()/number_of_student)).longValue();//for pagination

String downloadStudentLink = "download_search_student_result.jsp" + parameterList + "&number_of_student=" + studentcount;
String printStudentLink = "admin_print_search_student_result.jsp" + parameterList + "&from_row=" + from_row;

%>


<html <%if (user.getLanguageId()>0 && oDictionary.getLanguageInfo(user.getLanguageId()).getDirection()==1) out.print("dir='rtl'");%>>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15"/>
<title><%if (user.getRole()==6) out.print(oDictionary.getTranslatedWord(userLanguageId, "Sub-Administrator", adminId)); else out.print(oDictionary.getTranslatedWord(userLanguageId, "Administrator", adminId));%></title>
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta name="Microsoft Theme" content="blocks 000, default">
<meta name="Microsoft Border" content="tlb, default">

</head>


<body bgcolor="#FFFFFF" text="#000000" link="#CC0000" vlink="#CC0000" alink="#CC0000" leftmargin=5 topmargin=5 marginheight="0" marginwidth="0" onResize="if (navigator.family == 'nn4') window.location.reload()">


<p>
<table width=100%>
<td>
<img src="images/search.gif"> <b><font color="#666666" face="Arial, Arial, Helvetica" size="5"><%=oDictionary.getTranslatedWord(userLanguageId, "Search Result", adminId)%> &nbsp;&nbsp;</font></b>
</td>
<td align=right>
<table>
<%if (user.getRole()==4 || (user.getRole()==6 && (user.getOptions().indexOf("[STUDENT_RECORDS=") != -1 ))) {%>
<td>
&nbsp;<img src="images/write.gif"> <font face=arial size=2 color="#666666"><b><a href="new_student.jsp"><%=oDictionary.getTranslatedWord(userLanguageId, "New Student", adminId)%></a></font></b>
</td>
<%} %>
<td>
&nbsp;<img src="images/search.gif"> <font face=arial size=2 color="#666666"><b><a href="admin_search_student.jsp"><%=oDictionary.getTranslatedWord(userLanguageId, "Search Student", adminId)%></a></font></b>
</td>
<td>
&nbsp;<img src="images/read.gif"> <font face=arial size=2 color="#666666"><b><a href="students.jsp"><%=oDictionary.getTranslatedWord(userLanguageId, "Student Directory", adminId)%></a></font></b>
</td>
</table>
</td>
</table>


<%if (user.getRole()==4 || (user.getRole()==6 && (user.getOptions().indexOf("[STUDENT_RECORDS=F]") != -1 || user.getOptions().indexOf("[STUDENT_RECORDS=V]") != -1))) {%>

<table width="100%">
<tr>
<td>
    <%@ include file="paginate.jsp" %>
</td>

<td align="right">
<table>
<tr>
<td>
<img src="images/download.jpg">
<a href="<%=downloadStudentLink%>" target=_><font face=arial size=-1>[<%=oDictionary.getTranslatedWord(userLanguageId, "Download search result", adminId)%>]</font></a>
</td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="<%=printStudentLink%>" target=_><img border=0 src="images/printer.gif"><font face=arial size=-1>[<%=oDictionary.getTranslatedWord(userLanguageId, "Print search result", adminId)%>]</font></a>
</td>
</tr>
</table>
</tr>
</table>

</font>
<table border="0" cellpadding="1" cellspacing="0" style="border-collapse: collapse" width="100%" id="AutoNumber1" bordercolordark="#666666" bordercolorlight="#999999">

<%if (!columns.equals("")) {%>

<tr>
<td nowrap bgcolor="<%=user.getColor()%>" bordercolor="#CC3300"><font face="Arial, Arial, Helvetica" size=2><b><%=oDictionary.getTranslatedWord(userLanguageId, "Student Name", adminId)%></b></font></td>
<%for (int i=0; i<oVectorColumns.size(); i++) {%>
<td nowrap bgcolor="<%=user.getColor()%>" bordercolor="#CC3300"><font face="Arial, Arial, Helvetica" size=2><b><%=oVectorColumns.get(i)%></b></font></td>
<%}%>
</tr>

<%

    for (StudentInfo studentinfo:oVector) {

        userDirectoryVector.add(new Long(studentinfo.getStudentId()));

        java.util.HashMap oHashMapProfielValues = oExtendedProfile.getProfileFieldValues(studentinfo.getStudentId(), 1, user.getAdminId());
        java.util.Vector oVectorStudentAllPrograms = registration.getStudentAllProgrammes(studentinfo.getStudentId(), user.getAdminId());

        String programname = "";
        String levelname = "";
        String programlevelname = "";
        String RegistrationDate="";

那么,清理这些而不是分析不是更好吗?我认为答案是肯定的

于 2013-03-14T11:12:35.890 回答