JSP 實用程序之簡易頁面編輯器
來源:程序員人生 發布時間:2016-06-22 08:51:42 閱讀次數:2419次
需求:提供1頁面,放置“幫助”、“版權”文字內容,特點:靜態頁面,不必讀數據庫,只是應付字眼上頻繁的修改;沒有復雜的交互,不必 JavaScript;沒有圖片,不需要文件上傳。
給出的方案:提供1頁面和簡易的后臺管理,功能單1,只是編輯頁面(只是修改字體、大小、粗體、斜體等的功能)。
實現思路:純 JSP 展現,管理界面用 HTTP Basic 登入,通過1個 JS 寫成 HTML 編輯器修改頁面內容。直接修改服務器磁盤文件。
界面以下,右圖是后臺編輯。
值得1提的是,Tomcat 7 下 JSP 默許的 Java 語法仍舊是 1.6 的。在 JSP 里面嵌入 Java 1.7 特性的代碼會拋出“Resource specification not allowed here for source level below 1.7”的異常。因而需要修改 Tomcat/conf/web.xml 里面的配置文件,找到 <servlet> 節點,加入下面粗體部份才可以。注意是 jsp 節點,不是 default 節點(很類似)。
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<strong> <init-param>
<param-name>compilerSourceVM</param-name>
<param-value>1.7</param-value>
</init-param>
<init-param>
<param-name>compilerTargetVM</param-name>
<param-value>1.7</param-value>
</init-param></strong>
<load-on-startup>3</load-on-startup>
</servlet>
訪問的 jsp 其實只有兩個 /index.jsp 和 /admin/index.jsp,分別是靜態頁面和后臺編輯頁面。/admin/action.jsp 用于接收保存的 action,數據由表單 POST 過來。functions.jsp 就是全部的業務邏輯代碼,通過 <%@include file="functions.jsp"%>,它不能單獨給外界 url 訪問。
我們先看看 /index.jsp。
<%@page pageEncoding="UTF⑻"%>
<html>
<head>
<title>幫助</title>
<meta charset="utf⑻" />
<!--寬度 320px -->
<meta name="viewport" content="width=320,user-scalable=0,initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0" />
<style>
html {
font-size: 15px;
}
body {
padding: 0;
margin: 0 auto;
max-width: 600px;
-webkit-font-smoothing: antialiased;
font-family: "Microsoft YaHei", "ff-tisa-web-pro⑴", "ff-tisa-web-pro⑵",
"Lucida Grande", "Hiragino Sans GB", "Hiragino Sans GB W3", Arial;
background-color: #ebebeb;
}
h1 {
text-align: center;
font-size: 1.5rem;
letter-spacing: 2px;
color: #864c24;
border-bottom: #e0c494 solid 1px;
padding: 2% 0;
}
h2 {
font-size: 1rem;
letter-spacing: 1px;
color: #4c4c4c;
padding-bottom:0;
margin: 0;
}
p {
text-align: justify;
font-size: 1rem;
color: #818181;
margin: 1% 0;
margin-top:0;
}
ol {
padding: 0;
margin: 0;
}
ol {
}
ol>li>:first-child {
/* Make Firefox put the list marker inside */
/* https://bugzilla.mozilla.org/show_bug.cgi?id=36854 "if list-style-position is inside, bullet takes own line" */
display: inline;
}
ol>li>:first-child:after {
/* Add the margin that was lost w/ display: inline */
/* Firefox 10 displays this as block */
/* Safari 5.1.2 and Chrome 17.0.963.56 don't */
content: "";
display: block;
}
li {
padding: 5% 2%;
list-style-position: inside;
border-bottom: 1px solid #dddddb;
}
.text {
color: #a8a8a8;
font-size: 1rem;
font-weight: bold;
padding: 2%;
}
</style>
</head>
<body>
<!-- Editable AREA|START --> <h1>幫助</h1>
<div class="text">常見問題</div>
<ol>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
<li>
<h2>Power TV的資費是怎樣收取的?</h2>
<p>12元Power TV手電機視包月,產品代碼88888888,12元/月;省內用戶省內使用配送3G/月定向流量,流量僅用于使用Power TV,超過定向流量部份按標準資費收取; </p>
</li>
</ol>
<!-- Editable AREA|END -->
</body>
</html>
這份 JSP 與1般 JSP 并沒有特異,只不過大家有無留意到兩段注釋:<!-- Editable AREA|START --> 和 <!-- Editable AREA|END --> ——這就是我們約定的“可編輯”范圍。固然,使用自定義的 HTML Tag 也能夠,只要定義了1個范圍便可。1份網頁,不過是 HTML。對其中欲編輯的東西,我們定義1個范圍指明哪些地方需要編輯,就能夠了。至于為何不讓全部的頁面可以編輯?是由于我們不想用戶對頁面其它部份進行編輯,萬1修改了的關鍵地方造成了毛病,那可不好。
好了,怎樣讓這個 /index.jsp 編輯呢?就是利用 Java 讀取磁盤的方法來做的。在這個之前,得先登錄到 /admin/index.jsp。這里我們通過 HTTP Basic Authorization 來做用戶認證,不必數據庫。如果需要修改 賬號密碼,打開 admin/functions.jsp,編輯頭部份便可:
<%!
public static final String userid = "admin", pwd = "123123";
....
%>
不過筆者 HTTP Basic Authorization 遇到了個小問題,就是閱讀器彈出的對話框,不知怎樣修改其中的提示文字,試過幾種方法,要末不顯示,要末亂碼。如果知道的童鞋還請告知12!
action.jsp 也要作認證的限制,不然等因而個漏洞可讓他人 POST 任何數據到頁面。
<%@page pageEncoding="UTF⑻"%>
<%@include file="functions.jsp"%>
<%
if (checkAuth(request.getHeader("Authorization"), userid, pwd)) {
request.setCharacterEncoding("utf⑻");
if (request.getMethod().equalsIgnoreCase("POST")) {
String contentBody = request.getParameter("contentBody"), path = Mappath(getEditJSP(request));
System.out.println("path:::" + path);
save_jsp_fileContent(path, contentBody);
out.println("<script>alert('修改成功!');window.location = document.referrer;</script>");
} else {
out.println("method error");
}
} else {
%>
<html>
<body>
非法登錄!
</body>
</html>
<%
}
%>
修改下頁面,點擊保存就能夠修改頁面了。
至于 HTML 如何編輯?這個答案想必大家都清楚,使用 HTML 可視化編輯器便可,在線的哦,而不是甚么 Dreamweaver、FrontPage、VS Web 之類啦。老人們用過的就是有 FCKEditror 呀、TinyMCE Editor,近幾年好像喜歡用國產了,我就不知道了。現在這個用的是我自己寫,功能比較單1的。
核心邏輯是通過下面的代碼弄定的。
<%@page pageEncoding="UTF⑻" import="sun.misc.BASE64Decoder, java.io.*"%>
<%!
public static final String userid = "admin", pwd = "86006966";
// 檢查 HTTP Basic 認證
/**
* 是不是空字符串
*
* @param str
* @return
*/
public static boolean isEmptyString(String str) {
return str == null || str.trim().isEmpty();
}
/**
* 是不是不合法的數組
*
* @param arr
* @return
*/
public static boolean isBadArray(String[] arr) {
return arr == null || arr.length != 2;
}
/**
*
* @param authorization
* 認證后每次HTTP要求都會附帶上 Authorization 頭信息
* @param username
* 用戶名
* @param password
* 密碼
* @return true = 認證成功/ false = 需要認證
*/
public static boolean checkAuth(String authorization, String username, String password) {
if (isEmptyString(authorization))
return false;
String[] basicArray = authorization.split("\\s+");
if (isBadArray(basicArray))
return false;
String idpass = null;
try {
byte[] buf = new BASE64Decoder().decodeBuffer(basicArray[1]);
idpass = new String(buf, "UTF⑻");
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (isEmptyString(idpass))
return false;
String[] idpassArray = idpass.split(":");
if (isBadArray(idpassArray))
return false;
return username.equalsIgnoreCase(idpassArray[0]) && password.equalsIgnoreCase(idpassArray[1]);
}
/**
* 可編輯標識開始
*/
private final static String startToken = "<!-- Editable AREA|START -->";
/**
* 可編輯標識結束
*/
private final static String endToken = "<!-- Editable AREA|END -->";
/**
* 根據 頁面中可編輯區域之標識,取出來。
*
* @param fullFilePath
* 完全的 jsp 文件路徑
* @return 可編輯內容
* @throws IOException
*/
public static String read_jsp_fileContent(String fullFilePath) throws IOException {
String jsp_fileContent = readFile(fullFilePath);
int start = jsp_fileContent.indexOf(startToken), end = jsp_fileContent.indexOf(endToken);
try {
jsp_fileContent = jsp_fileContent.substring(start + startToken.length(), end);
} catch (StringIndexOutOfBoundsException e) {
jsp_fileContent = null;
String msg = "頁面文件" + fullFilePath + "中沒有標記可編輯區域之標識。請參考:" + startToken + "/" + endToken;
throw new IOException(msg);
}
return jsp_fileContent;
}
/**
* 要求附帶文件參數,將其轉換真實的磁盤文件路徑
*
* @param rawFullFilePath
* URL 提交過來的磁盤文件路徑,可能未包括文件名或加了很多 url 參數
* @return 完全的磁盤文件路徑
*/
static String getFullPathByRequestUrl(String rawFullFilePath) {
if (rawFullFilePath.indexOf(".jsp") == ⑴)
rawFullFilePath += "/index.jsp"; // 加上 擴大名
if (rawFullFilePath.indexOf("?") != ⑴) // 去掉 url 參數
rawFullFilePath = rawFullFilePath.replaceAll("\\?.*$", "");
return rawFullFilePath;
}
/**
* 保存要修改的頁面
*
* @param rawFullFilePath
* 真實的磁盤文件路徑
* @param newContent
* 新提交的內容
* @throws IOException
*/
public static void save_jsp_fileContent(String rawFullFilePath, String newContent) throws IOException {
String fullFilePath = getFullPathByRequestUrl(rawFullFilePath); // 真實的磁盤文件路徑
String jsp_fileContent = readFile(fullFilePath), toDel_fileContent = read_jsp_fileContent(fullFilePath);// 讀取舊內容
//System.out.println(jsp_fileContent);
//System.out.println(toDel_fileContent);
if (toDel_fileContent != null) {
jsp_fileContent = jsp_fileContent.replace(toDel_fileContent, newContent);
save2file(fullFilePath, jsp_fileContent); // 保存新內容
} else {
throw new IOException("頁面文件中沒有標記可編輯區域之標識。請參考: startToken/endTpoken");
}
}
/**
* 讀取文件
*
* @param filename
* @return
* @throws IOException
*/
public static String readFile(String filename) throws IOException {
File file = new File(filename);
if (!file.exists())
throw new FileNotFoundException(filename + " 不存在!");
try (FileInputStream is = new FileInputStream(file);) {
String line = null;
StringBuilder result = new StringBuilder();
try (InputStreamReader isReader = new InputStreamReader(is, "UTF⑻");
BufferedReader reader = new BufferedReader(isReader);) {
while ((line = reader.readLine()) != null) {
result.append(line);
result.append('\n');
}
} catch (IOException e) {
System.err.println(e);
}
return result.toString();
} catch (IOException e) {
System.err.println("讀取文件流出錯!" + filename);
throw e;
}
}
/**
* 寫文件不能用 FileWriter,緣由是會中文亂碼
*
* @param filename
* @param content
* @throws IOException
*/
public static void save2file(String filename, String content) throws IOException {
try (FileOutputStream out = new FileOutputStream(filename);
// OutputStreramWriter將輸出的字符流轉化為字節流輸出(字符流已帶緩沖)
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8");) {
writer.write(content);
} catch (IOException e) {
System.err.println("寫入文件" + filename + "失敗");
throw e;
}
}
/**
* 輸入1個相對地址,補充成為絕對地址 相對地址轉換為絕對地址,并轉換斜杠
*
* @param relativePath
* 相對地址
* @return 絕對地址
*/
public String Mappath(String relativePath) {
String absoluteAddress = getServletContext().getRealPath(relativePath); // 絕對地址
if (absoluteAddress != null)
absoluteAddress = absoluteAddress.replace('\\', '/');
return absoluteAddress;
}
public String getEditJSP(HttpServletRequest request) {
String uri = request.getRequestURI().replaceAll("admin/\\w+", "index");
uri = uri.replace(request.getContextPath(), "");
return uri;
}
%>
用戶憑賬號密碼登入簡易的后臺,通過可視化編輯器便可修改頁面內容,立刻修改,立刻產生效果,簡單快捷——把頁面開放出來允許自主編輯這樣會提高效力——減少來回修改的次數。
不足的地方,還請大家指出。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈