jasper 获取当前日期

为了对我的JSP执行一些检查和统计分析,我需要一个包含在其中的元素的类似于DOM的层次模型。 但是,解析JSP页面并不是一件容易的事,最好留给它一个出色的工具-Tomcat,Jetty,GlassFish以及其他所有工具都可以使用Jasper JSP编译器。

有一种简单的方法可以调整它以生成所需的任何输出,以将JSP转换为所需的任何形式,包括页面的对象模型:

  1. 定义一个Node.Visitor子类来处理JSP的节点(标签等)
  2. 编写一个简单的Compiler子类,重写其generateJava()来调用访问者
  3. 继承编译器执行程序JspC的子类,重写其方法getCompilerClassName()以返回您自己的编译器的类

让我们看一下代码。

实作

1.自定义访问者

编译器将调用Visitor来处理已解析的JSP的树对象模型。 此实现仅打印有关页面中有趣的节点子集的信息,以使其嵌套清晰。

package org.apache.jasper.compiler;import java.util.LinkedList;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.Node.CustomTag;
import org.apache.jasper.compiler.Node.ELExpression;
import org.apache.jasper.compiler.Node.IncludeDirective;
import org.apache.jasper.compiler.Node.Visitor;
import org.xml.sax.Attributes;public class JsfElCheckingVisitor extends Visitor {private String indent = "";@Overridepublic void visit(ELExpression n) throws JasperException {logEntry("ELExpression", n, "EL: " + n.getEL());super.visit(n);}@Overridepublic void visit(IncludeDirective n) throws JasperException {logEntry("IncludeDirective", n, toString(n.getAttributes()));super.visit(n);}@Overridepublic void visit(CustomTag n) throws JasperException {logEntry("CustomTag", n, "Class: " + n.getTagHandlerClass().getName() + ", attrs: "+ toString(n.getAttributes()));doVisit(n);indent += " ";visitBody(n);indent = indent.substring(0, indent.length() - 1);}private String toString(Attributes attributes) {if (attributes == null || attributes.getLength() == 0) return "";LinkedList<String> details = new LinkedList<String>();for (int i = 0; i < attributes.getLength(); i++) {details.add(attributes.getQName(i) + "=" + attributes.getValue(i));}return details.toString();}private void logEntry(String what, Node n, String details) {System.out.println(indent + n.getQName() + " at line:"+ n.getStart().getLineNumber() + ": " + details);}}

笔记:

  • 访客必须位于org.apache.jasper.compiler包中,因为基本类org.apache.jasper.compiler.Node是包私有的
  • visitBody方法触发对嵌套节点的处理
  • 还有更多我可以覆盖的方法(和通行方法doVisit),但是我只选择了对我来说有趣的那些方法
  • 节点的属性为... sax类型。 Attributes ,它包含属性名称和值作为字符串
    • attribute.getType(i)通常是CDATA
  • Node结构包含有关父节点,标签名称,标签处理程序类,源文件的相应行以及源文件的名称的信息以及其他有用信息
  • CustomTag可能是最有趣的节点类型,例如,所有JSF标签都属于这种类型

输出示例(对于JSF页面)

jsp:directive.include at line:5: [file=includes/stdjsp.jsp]
jsp:directive.include at line:6: [file=includes/ssoinclude.jsp]
f:verbatim at line:14: Class: com.sun.faces.taglib.jsf_core.VerbatimTag, attrs:
htm:div at line:62: Class: com.exadel.htmLib.tags.DivTag, attrs: [style=width:100%;]h:form at line:64: Class: com.sun.faces.taglib.html_basic.FormTag, attrs: [id=inputForm]htm:table at line:66: Class: com.exadel.htmLib.tags.TableTag, attrs: [cellpadding=0, width=100%, border=0, styleClass=clear box_main]htm:tr at line:71: Class: com.exadel.htmLib.tags.TrTag, attrs:htm:td at line:72: Class: com.exadel.htmLib.tags.TdTag, attrs:f:subview at line:73: Class: com.sun.faces.taglib.jsf_core.SubviewTag, attrs: [id=cars]jsp:directive.include at line:74: [file=/includes/cars.jsp]h:panelGroup at line:8: Class: com.sun.faces.taglib.html_basic.PanelGroupTag, attrs: [rendered=#{bookingHandler.flowersAvailable}]
...htm:tr at line:87: Class: com.exadel.htmLib.tags.TrTag, attrs: [style=height:5px]htm:td at line:87: Class: com.exadel.htmLib.tags.TdTag, attrs:

(我不打印“关闭标签”,因为很明显,当缩进相同或较小的另一个节点出现或输出结束时,标签结束。)

2.编译器子类

重要的部分是我刚刚复制的generateJava,从中删除了一些代码并添加了对Visitor的调用。 所以实际上下面清单中的3行是新的(6,56,70)

public class OnlyReadingJspPseudoCompiler extends Compiler {/** We're never compiling .java to .class. */@Override protected void generateClass(String[] smap) throws FileNotFoundException,JasperException, Exception {return;}/** Copied from {@link Compiler#generateJava()} and adjusted */@Override protected String[] generateJava() throws Exception {// Setup page info areapageInfo = new PageInfo(new BeanRepository(ctxt.getClassLoader(),errDispatcher), ctxt.getJspFile());// JH: Skipped processing of jsp-property-group in web.xml for the current pageif (ctxt.isTagFile()) {try {double libraryVersion = Double.parseDouble(ctxt.getTagInfo().getTagLibrary().getRequiredVersion());if (libraryVersion < 2.0) {pageInfo.setIsELIgnored("true", null, errDispatcher, true);}if (libraryVersion < 2.1) {pageInfo.setDeferredSyntaxAllowedAsLiteral("true", null,errDispatcher, true);}} catch (NumberFormatException ex) {errDispatcher.jspError(ex);}}ctxt.checkOutputDir();try {// Parse the fileParserController parserCtl = new ParserController(ctxt, this);// Pass 1 - the directivesNode.Nodes directives =parserCtl.parseDirectives(ctxt.getJspFile());Validator.validateDirectives(this, directives);// Pass 2 - the whole translation unitpageNodes = parserCtl.parse(ctxt.getJspFile());// Validate and process attributes - don't re-validate the// directives we validated in pass 1/*** JH: The code above has been copied from Compiler#generateJava() with some* omissions and with using our own Visitor.* The code that used to follow was just deleted.* Note: The JSP's name is in ctxt.getJspFile()*/pageNodes.visit(new JsfElCheckingVisitor());} finally {}return null;}/*** The parent's implementation, in our case, checks whether the target file* exists and returns true if it doesn't. However it is expensive so* we skip it by returning true directly.* @see org.apache.jasper.JspCompilationContext#getServletJavaFileName()*/@Override public boolean isOutDated(boolean checkClass) {return true;}}

笔记:

  • 我从生成Java中删除了许多对我来说不重要的代码; 对于与我预期不同的分析类型,某些代码可能会有用,因此请查看原始的Compiler类,然后自己决定。
  • 我不太在乎JSP EL,因此可以优化编译器,使其仅需一次通过。

3.编译器执行器

直接使用编译器很困难,因为它取决于许多复杂的设置和对象。 因此,最简单的方法是重用Ant任务JspC,这还有查找要处理的JSP的额外好处。 如前所述,关键是重写getCompilerClassName以返回编译器的类(第8行)

import org.apache.jasper.JspC;/** Extends JspC to use the compiler of our choice; Jasper version 6.0.29. */
public class JspCParsingToNodesOnly extends JspC {/** Overriden to return the class of ours (default = null => JdtCompiler) */@Override public String getCompilerClassName() {return OnlyReadingJspPseudoCompiler.class.getName();}public static void main(String[] args) {JspCParsingToNodesOnly jspc = new JspCParsingToNodesOnly();jspc.setUriroot("web"); // where to search for JSPs//jspc.setVerbose(1);     // 0 = false, 1 = truejspc.setJspFiles("helloJSFpage.jsp"); // leave unset to process all; comma-separatedtry {jspc.execute();} catch (JasperException e) {throw new RuntimeException(e);}}
}

笔记:

  • JspC通常会在指定的Uriroot下找到所有文件,但是您可以通过将其逗号分隔的名称传递给setJspFiles来告诉它忽略所有选定的文件。

编译依赖

以您的常春藤形式:

<dependency name="jasper" org="org.apache.tomcat" rev="6.0.29">
<dependency name="jasper-jdt" org="org.apache.tomcat" rev="6.0.29">
<dependency name="ant" org="org.apache.ant" rev="1.8.2">

执照

这里的所有代码都直接来自Jasper,因此属于同一许可证,即Apache许可证,版本2.0 。

结论

Jasper并不是真正为扩展和模块化而设计的,因为关键的Node类是程序包私有的,并且其API非常复杂,以致仅重用其中的一部分非常困难。 幸运的是,通过提供一些“伪”对象,Ant任务JspC使它可以在servlet容器之外使用,并且有一种方法可以通过很少的工作来调整它以满足我们的需求,尽管要弄清楚它并不容易。 我不得不应用一些肮脏的技巧,即使用包私有类中的内容,并覆盖一个不打算被覆盖的方法( generateJava ),但它可以工作并提供非常有价值的输出,这使得您可以做任何想做的事情用一个JSP来做。

参考:在我们的Java博客上,与我们的JCG合作伙伴 JakubHolý 合作 ,通过Jasper入侵获取JSP页面的对象模型 。
快乐的编码...
拜伦
相关文章:
  • Java Code Geeks Andygene Web原型
  • 为什么自动化测试可以提高您的开发速度
  • 代码质量对客户很重要。 很多。
  • 使用FindBugs产生更少的错误代码
  • 针对用户和新采用者的敏捷软件开发建议

翻译自: https://www.javacodegeeks.com/2011/06/hacking-jasper-to-get-object-model-of.html

jasper 获取当前日期

jasper 获取当前日期_入侵Jasper以获取JSP页面的对象模型相关推荐

  1. 入侵Jasper以获取JSP页面的对象模型

    为了对我的JSP进行一些检查和统计分析,我需要一个包含在其中的元素的类似于DOM的层次模型. 但是,解析JSP页面并不是一件容易的事,最好留给它一个出色的工具-Tomcat,Jetty,GlassFi ...

  2. 关于一加载jsp页面就跳转到servlet获取数据然后再跳回jsp页面的问题

    下面来说我遇到的问题: 上一篇文章中写的是jsp+javabean实现商品分页  浏览,即model1的开发模式,现在要改为 jsp+sevlet+javabean 即model2了  之前在jsp处 ...

  3. python3获取当前日期_如何在python3中获取当前日期和时间? – Python3教程

    在本文中,你将学习如何用Python获取今天的日期和当前的日期和时间,我们还将使用strftime()方法以不同的格式格式化日期和时间. 获取当前日期的方法有很多,我们将使用datetime模块的da ...

  4. mysql 获取当前日期_详解mysql 获取当前日期及格式化

    本篇文章主要介绍了mysql 获取当前日期及格式化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下. MySQL 获取当前日期及日期格式 获取系统日期: NOW() 格式化日期: DATE_FORM ...

  5. JAVA里的jsp网页背景_【JavaWeb】JSP 页面

    JSP 页面 简介 JSP(Java Server Pages),即 Java 的服务器页面.它的主要作用是代替 Servlet 程序回传 HTML 页面的数据,因为 Servlet 程序回传 HTM ...

  6. java jsp公共异常页面_实际应用中JSP页面的异常处理

    打开浏览器,访问一个链接或者输入url,"咚"的敲下回车... 哗啦啦,一大堆看不懂的异常信息一下×××出来,塞满整个页面,我勒个去,吓死人了... 在实际开发中,用户访问网站的时 ...

  7. button jsp隐藏_关于在同一JSP页面通过隐藏域传值的问题?

    1.jsp只能给javascript赋值,例如:var selectValues_1=""; . 2.但不能反过来赋值,因为jsp是在先服务器上执行,服务器并不解释其中的静态代码, ...

  8. 从一个jsp页面跳转到另一个jsp页面时的参数传递

      1.从一个jsp页面跳转到另一个jsp页面时的参数传递 (1)使用request对象获取客户端提交的信息 login.jsp页面代码如下: [java] view plaincopy <%@ ...

  9. 解决Jsp运行org.apache.jasper.JasperException: Unable to compile class for JSP:问题

    解决Jsp运行org.apache.jasper.JasperException: Unable to compile class for JSP:问题 参考文章: (1)解决Jsp运行org.apa ...

最新文章

  1. 春节囤货清单 | 15篇近期值得读的AI论文
  2. 软件编程思想的些许感想
  3. 将字符串的部分保存,剩余删去,或只保留指定一段子字符串
  4. java 等待几秒_问懵逼:请站在 JVM 角度谈谈 Java 的锁?
  5. Hadoop笔记整理(三):Zookeeper
  6. 使用jquery.form.js实现form表单无刷新提交简单示例
  7. html5手机常亮,vue开发的webapp中的手机物理返回键,以及屏幕常亮处理
  8. 小白用python处理excel文件-Python3操作Excel文件(读写)的简单实例
  9. 全面了解CCD摄像机
  10. Linux中缺32位运行库steam,Steam运行库修复工具 32位/64位 最新免费版
  11. visio一分二的箭头_Visio如何画各种线条与箭头?
  12. 电机与拖动 - 7 直流电机
  13. TeeChart Pro ActiveX教程(十九):TeeChart工具集(六)
  14. http状态码为499的解决办法
  15. datastage错误之Consumed more than 100,000 bytes looking for record delimiter; aborting
  16. 几个巧妙的电流检测电路
  17. [java]深入剖析Java性能监控调优视频教程
  18. 31、Java——JDBC实现账号密码登录
  19. 美好只在一瞬间[frwy]
  20. 我的开源: UnInstaller for Windows(VBScript)

热门文章

  1. java安装显示更改_java 安装与配置
  2. mybatis的$和#详解分析
  3. git删除本地分支、删除远程分支 复制分支
  4. Java 虚拟机部分面试题
  5. python测试开发面试题_python测试开发面试之深浅拷贝
  6. jvm(7)-虚拟机类加载机制
  7. java数据库编程——执行SQL 语句
  8. java中的方法求和_在Java中模拟求和类型的巧妙解决方法
  9. netty socket_Netty:另一种Web(Socket)服务器
  10. netflix_学习Netflix管理员–第1部分