• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    JSP实用教程之简易页面编辑器的实现方法(附源码)

    前言

    实现一个简易的页面编辑器是大家在学习jsp的时候经常会遇到的一个需求,发现网上这方便的资料不多,所以想着自己总结下,本文详细介绍了JSP简易页面编辑器的实现方法,下面话不多说,来一起看看详细的介绍:

    需求

    提供一页面,放置“帮助”、“版权”文字内容,特点:静态页面,无须读数据库,只是应付字眼上频繁的修改;没有复杂的交互,无须 JavaScript;没有图片,不需要文件上传。

    给出的方案:提供一页面和简易的后台管理,功能单一,只是编辑页面(只是修改字体、大小、粗体、斜体等的功能)。
    实现思路:纯 JSP 展示,管理界面用 HTTP Basic 登入,通过一个 js 写成 HTML 编辑器修改页面内容。直接修改服务器磁盘文件。

    界面如下,右图是后台编辑。


    值得一提的是,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> 节点( servlet-name>jsp/servlet-name>  的才是),加入下面最后两个 init-param 节点部分。注意是 servlet-name>jsp/servlet-name> 节点才可以,不是 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> 
     
     
      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> 
     
     
      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-8"%> 
    html> 
     head> 
      title>帮助/title> 
      meta charset="utf-8" /> 
       !--宽度 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-1", "ff-tisa-web-pro-2", 
      "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 与一般 JSP 并无特异,只不过大家有没有留意到两段注释: !-- Editable AREA|START --> !-- Editable AREA|END --> ——这就是我们约定的“可编辑”范围。当然,使用自定义的 HTML Tag 也可以,只要定义了一个范围即可。一份网页,无非是 HTML。对于其中欲编辑的东西,我们定义一个范围指明哪些地方需要编辑,就可以了。至于为什么不让全部的页面可以编辑?是因为我们不想用户对页面其它部分进行编辑,万一修改了的关键地方造成了错误,那可不好。

    好了,怎么让这个 /index.jsp 编辑呢?就是利用 Java 读取磁盘的方法来做的。在这个之前,得先登录到 /admin/index.jsp。这里我们通过 HTTP Basic Authorization 来做用户认证,无须数据库。如果需要修改 账号密码,打开 admin/functions.jsp,编辑头部分即可:

    %!
     public static final String userid = "admin", pwd = "123123"; 
     ....
    %>

    不过笔者调试 HTTP Basic Authorization 遇到了个小问题,就是浏览器弹出的对话框,不知怎么修改其中的提示文字,试过几种方法,要么不显示,要么乱码。如果知道的童鞋还请告知一二!

    action.jsp 也要作认证的限制,不然等于是个漏洞可以让别人 POST 任何数据到页面。

    %@page pageEncoding="UTF-8"%> 
    %@include file="functions.jsp"%> 
    % 
     
    if (checkAuth(request.getHeader("Authorization"), userid, pwd)) { 
     request.setCharacterEncoding("utf-8"); 
     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,近几年好像喜欢用国产了,我就不知道了。现在这个用的是我自己写,功能比较单一的。

    核心逻辑是通过下面的代码搞定的。

    %@page pageEncoding="UTF-8" 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-8"); 
      } 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") == -1) 
       rawFullFilePath += "/index.jsp"; // 加上 扩展名 
     
      if (rawFullFilePath.indexOf("?") != -1) // 去掉 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-8"); 
         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; 
      } 
     } 
      
     /** 
      * 输入一个相对地址,补充成为绝对地址 相对地址转换为绝对地址,并转换斜杠 
      * 
      * @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; 
     } 
    %> 

    用户凭账号密码登入简易的后台,通过可视化编辑器即可修改页面内容,立刻修改,立刻产生效果,简单快捷——把页面开放出来允许自主编辑这样会提高效率——减少来回修改的次数。

    完整源码下载:http://xiazai.jb51.net/201707/yuanma/jsp-page(jb51.net).rar

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

    您可能感兴趣的文章:
    • js 公式编辑器 - 自定义匹配规则 - 带提示下拉框 - 动态获取光标像素坐标
    • 不到200行 JavaScript 代码实现富文本编辑器的方法
    • 使用JavaScript实现表格编辑器(实例讲解)
    • Vue.js结合Ueditor富文本编辑器的实例代码
    • JS模仿编辑器实时改变文本框宽度和高度大小的方法
    • 分享9个最好用的JavaScript开发工具和代码编辑器
    • node.js集成百度UE编辑器
    • Javascript实现简单的富文本编辑器附演示
    • javascript获取ckeditor编辑器的值(实现代码)
    • 4个顶级JavaScript高级文本编辑器
    上一篇:web前端超出两行用省略号表示的实现方法
    下一篇:JSP实用教程之简易文件上传组件的实现方法(附源码)
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    JSP实用教程之简易页面编辑器的实现方法(附源码) JSP,实用,教程,之,简易,页面,