Template和JSP技术

springboot 视图 Template、JSP 加载说明 最近将 springboot 升级到 3.3.0 版本;java 升级到 21 后,发现打包成 jar 后启动时,访问不到 JSP了;但通过 mvn spring-boot:run 命令启动可以正常访问;原来 jsp 文件放在 META-INF/resources/ 目录下;使用 1.4.2.RELEASE 版本的maven-spring-boot-plugin 插件打包,使用 3.3.0 版本的插件打包; 阅读详情

(本文发于java emag第一期)
一、起源与现状:

关于Template和JSP的起源还要追述到Web开发的远古年代,那个时候的人们用CGI来开发web应用,在一个CGI程序中写HTML标签。

在这之后世界开始朝不同的方向发展:sun公司提供了类似于CGI的servlet解决方案,但是无论是CGI还是servlet都面对同一个问题:在程序里写html标签,无论如何都不是一个明智的解决方案。于是sun公司于1999年推出了JSP技术。而在另一个世界里,以PHP和ASP为代表的scriptlet页面脚本技术开始广泛应用。

不过即便如此,问题并没有结束,新的问题出现了:业务和HTML标签的混合,这个问题不仅导致页面结构的混乱,同时也使代码本身难以维护。

于是来自起源于70年代后期的MVC模式被引入开发。MVC的三个角色:Model——包含除UI的数据和行为的所有数据和行为。View是表示UI中模型的显示。任何信息的变化都由MVC中的第三个成员来处理——控制器。

在之后的应用中,出现了技术的第一次飞跃:前端的显示逻辑和后端的业务逻辑分离,COM组件或EJB或CORBA用于处理业务逻辑,ASP、JSP以及PHP被用于前端的显示。这个就是Web开发的Model 1阶段(页面控制器模式)。

不过这个开发模式有很多问题:

1.       页面中必须写入Scriptlet调用组件以获得所必需的数据。

2.       处理显示逻辑上Scriptlet代码和HTML代码混合交错。

3.       调试困难。JSP被编译成servlet,页面上的调试信息不足以定位错误。

这一切都是因为在Model 1中并没有分离视图和控制器。完全分离视图和控制器就成了必须。这就是Model 2。它把Model 1中未解决的问题——分离对组件(业务逻辑)的调用工作,把这部分工作移植到了控制器。现在似乎完美了,不过等等,原来的控制器从页面中分离后,页面所需的数据怎么获得,谁来处理页面显示逻辑?两个办法:1. 继续利用asp,php或者jsp等机制,不过由于它们是运行在web环境下的,他们所要显示的数据(后端逻辑产生的结果)就需要通过控制器放入request流中;2. 使用新手法——模板技术,使用独立的模板技术由于脱离的了web环境,会给开发测试带来相当的便利。至于页面所需数据传入一个POJO就行而不是request对象。

模板技术最先开始于PHP的世界,出现了PHPLIB Template和FastTemplate这两位英雄。不久模板技术就被引入到java web开发世界里。目前比较流行的模板技术有:XSTL,Velocity,JDynamiTe,Tapestry等。另外因为JSP技术毕竟是目前标准,相当的系统还是利用JSP来完成页面显示逻辑部分,在Sun公司的JSTL外,各个第三方组织也纷纷推出了自己的Taglib,一个代表是struts tablib。

二、 模板技术分析:

模板技术从本质上来讲,它是一个占位符动态替换技术。一个完整的模板技术需要四个元素:0. 模板语言,1. 包含模板语言的模板文件,2. 拥有动态数据的数据对象,3. 模板引擎。以下就具体讨论这四个元素。(在讨论过程中,我只列举了几个不同特点技术,其它技术或有雷同就不重复了)

1.       模板语言:

模板语言包括:变量标识和表达式语句。根据表达式的控制力不同,可以分为强控制力模板语言和弱控制力模板语言。而根据模板语言与HTML的兼容性不同,又可以分为兼容性模板语言和非兼容性模板语言。

模板语言要处理三个要点:

1. 标量标记。把变量标识插入html的方法很多。其中一种是使用类似html的标签;另一种是使用特殊标识,如Velocity或者JDynamiTe;第三种是扩展html标签,如tapestry。采用何种方式有着很多考虑,一个比较常见的考虑是“所见即所得”的要求。

2. 条件控制。这是一个很棘手的问题。一个简单的例子是某物流陪送系统中,物品数低于一定值的要高亮显示。不过对于一个具体复杂显示逻辑的情况,条件控制似乎不可避免。当你把类似于<IF condition=”$count <= 40”><then><span class=”highlight”>count </span></then></IF>引入,就象我们当初在ASP和PHP中所做得一样,我们将不得不再一次面对scriptlet嵌入网页所遇到的问题。我相信你和我一样并不认为这是一个好得的编写方式。实际上并非所有的模板技术都使用条件控制,很多已有的应用如PHP上中的以及我曾见过一个基于ASP.NET的应用,当然还有Java的JDynamiTe。这样网页上没有任何逻辑,不过这样做的代价是把高亮显示的选择控制移交给编程代码。你必需做个选择。也许你也象我一样既不想在网页中使用条件控制,也不想在代码中写html标记,但是这个显示逻辑是无可逃避的(如果你不想被你的老板抄鱿鱼的话),一个可行的方法是用CSS,在编程代码中决定采用哪个css样式。特别是CSS2技术,其selector机制,可以根据html类型甚至是element的attributes来apply不同的样式。

3. 迭代(循环)。在网页上显示一个数据表单是一个很基本的要求,使用集合标签将不可避免,不过幸运的是,它通常很简单,而且够用。特别值得一提的是PHP的模板技术和JDynamiTe技术利用html的注释标签很简单的实现了它,又保持了“所见既所得”的特性。

下面是一些技术的比较:

Velocity

变量定义:用$标志

表达式语句:以#开始

强控制语言:变量赋值:#set $this = "Velocity"

            外部引用:#include ( $1 )

            条件控制:#if …. #end

非兼容语言

JDynamiTe

变量定义:用{}包装

表达式语句:写在注释格式(<!--  à)中

弱控制语言

兼容语言

XSLT

变量定义:xml标签

表达式:xsl标签

强控制语言:外部引用:import,include

            条件控制:if,  choose…when…otherwise

非兼容语言

Tapestry

采用component的形式开发。

变量定义(组件定义):在html标签中加上jwcid

表达式语句:ognl规范

兼容语言

 

2.       模板文件:

模板文件指包含了模板语言的文本文件。

模板文件由于其模板语言的兼容性导致不同结果。与HTML兼容性的模板文件只是一个资源文件,其具有良好的复用性和维护性。例如JDynamiTe的模板文件不但可以在不同的项目中复用,甚至可以和PHP程序的模板文件互用。而如velocity的非兼容模板文件,由于其事实上是一个脚本程序,复用性和可维护性大大降低。

3.       拥有动态数据的数据对象:

模板文件包含的是静态内容,那么其所需的动态数据就需要另外提供。根据提供数据方式的不同可以分为3种:

1.       Map:利用key/value来定位。这个是最常见的技术。如velocity的VelocityContext就是包含了map对象。

Example.vm:

Hello from $name in the $project project.

 

Example.java:

VelocityContext context = new VelocityContext();

context.put("name", "Velocity");

context.put("project", " Jakarta ");

 

2.       DOM:直接操作DOM数据对象,如XSLT利用XPath技术。

3.       POJO:直接利用反射取得DTO对象,利用JavaBean机制取得数据。如Tapestry。

4.       模板引擎:

模板引擎的工作分为三步:

1. 取得模板文件并确认其中的模板语言符合规范。

比如velocity,确定#if有对应得#end等。Xml+xslt的模型中,xml文件标签是否完整等。在完成这些工作后,模板引擎通常会把模板文件解析成一颗节点树(包含模板文件的静态内容节点和模板引擎所定义的特殊节点)。

2. 取得数据对象。

        该数据对象一般通过程序传递引用实现。现有的大量框架在程序底层完成,处理方式也各自不同,有两种技术分别为推技术和拉技术。推技术:controller调用set方法把动态数据注入,模板引擎通过get方法获得,典型代表:Struts;拉技术:模板引擎根据配置信息,找到与view对应的model,调用model的get方法取得数据,典型代表:Tapestry。

3. 合并模板文件(静态内容)和数据对象(动态内容),并生成最终页面。

        合并的机制一般如下,模板引擎遍历这颗节点树的每一个节点,并render该节点,遇到静态内容节点按正常输入,遇到特殊节点就从数据对象中去得对应值,并执行其表达式语句(如果有的话)。

以下详细说明:

Velocity

Template template = Velocity.getTemplate("test.wm");

Context context = new VelocityContext();

context.put("foo", "bar");

context.put("customer", new Customer());

template.merge(context, writer);

当调用Velocity.getTemplate 方法时,将调用ResourceManger的对应方法。

ResourceManger先查看该模板文件是否在cache中,如果没有就去获取,生成resource对象并调用process()方法,确定该模板是否有效,如果有效,则在内存中生成一个Node树。

当调用template.merge()时,遍历这颗Node树,并调用每个Node的render方法。对于模板中的变量和对象Node,还将调用execute()方法,从context中取得value。

   注:ResourceManger在runtime/resource包下,Node在runtime/parser/node包下

Tapestry

Tapestry比较麻烦,先介绍一下http请求的处理过程。

当httprequest请求到达时。该请求被ApplicationServlet捕获,随后ApplicationServlet通过getEngine取到对应的Engine,通过该engine的getService拿到对应的service,调用其service方法执行http请求。

每个service通过RequestCycle对象的getPage方法取得Page对象,并将其设置为该Cycle对象的active Page。之后service调用renderResponse方法执行输出。

renderResponse调用page的getResponseWriter(output)取得writer对象,并把它传给cycle.renderPage(writer)方法,该方法调用page的renderPage方法。

Page执行renderPage时,首先判断是否有listener的请求,如果有则处理listener请求;然后调用BaseComponentTemplateLoader的process方法把模板文件载入并形成一个component节点树,依次执行节点的renderComponent方法。

每个component对象将通过ongl的机制取得对象属性。并把该值写入输入流。

例如:insert component

protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {

        if (cycle.isRewinding())

            return;

        Object value = getValue();

        if (value == null)

            return;

        String insert = null;

        Format format = getFormat();

        if (format == null) {

            insert = value.toString();

        }

        else{

            try{

                insert = format.format(value);

            }

            catch (Exception ex) {

                throw new ApplicationRuntimeException(

Tapestry.format("Insert.unable-to-format",value),this, getFormatBinding().getLocation(), ex);

            }

        }

        String styleClass = getStyleClass();

        if (styleClass != null) {

            writer.begin("span");

            writer.attribute("class", styleClass);

            renderInformalParameters(writer, cycle);

        }

        if (getRaw())

            writer.printRaw(insert);

        else

            writer.print(insert);

        if (styleClass != null)

            writer.end(); // <span>

    }

getValue为取得insert的value属性。

 

三、JSP技术分析

       1. JSP技术:

       JSP,一个伪装后的servlet。web server会对任何一个jsp都生成一个对应jsp类,打开这个类,就会发现,jsp提供的是一个代码生成机制,把jsp文件中所有的scriptlet原封不动的copy的到生成的jsp类中,同时调用println把所有的html标签输出。

Test.jsp:

<html>

<head><title>jsp test</title></head>

<body>

<table width="226" border="0" cellspacing="0" cellpadding="0">

   <tr><td><font face="Arial" size="2" color="#000066">

             <b class="headlinebold">The jsp test file</b>

       </tr></td> </font>  

</table>

<body>

</html>

Test_jsp.java:

package org.apache.jsp;

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

import org.apache.jasper.runtime.*;

 

public class Test _jsp extends HttpJspBase {

  private static java.util.Vector _jspx_includes;

  public java.util.List getIncludes() {

    return _jspx_includes;

  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)

        throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;

    javax.servlet.jsp.PageContext pageContext = null;

    HttpSession session = null;

    ServletContext application = null;

    ServletConfig config = null;

    JspWriter out = null;

    Object page = this;

    JspWriter _jspx_out = null;

 

    try {

      _jspxFactory = JspFactory.getDefaultFactory();

      response.setContentType("text/html;charset=ISO-8859-1");

      pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);

      application = pageContext.getServletContext();

      config = pageContext.getServletConfig();

      session = pageContext.getSession();

      out = pageContext.getOut();

      _jspx_out = out;

 

      out.write("<html>/r/n");

      out.write("<head><title>jsp test</title></head> /r/n");

      out.write("<body>/r/n");

      out.write("<table width=/"226/" border=/"0/" cellspacing=/"0/" cellpadding=/"0/">/r/n   ");

      out.write("<tr><td><font face=/"Arial /" size=/"2/" color=/"#000066/"> /r/n/t      ");

      out.write("<b class=/"headlinebold/">The jsp test file");

      out.write("</b>/r/n/t      ");

      out.write("</tr></td></font>/r/n/t ");

      out.write("</table>/r/n");

      out.write("<body>/r/n");

      out.write("</html>");

    } catch (Throwable t) {

      out = _jspx_out;

      if (out != null && out.getBufferSize() != 0)

        out.clearBuffer();

      if (pageContext != null) pageContext.handlePageException(t);

    } finally {

      if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);

    }

  }

}

 

       2. Taglib技术:

Taglib作为jsp之上的辅助技术,其工作本质依托与jsp技术,也是自定义标签翻译成java代码,不过这次和jsp略有不同,它还要经过几个过程。

先来看一下,实现一个tag的2个要点:

1. 提供属性的set方法,此后这个属性就可以在jsp页面设置。以jstl标签为例 c:out value=""/,这个value就是jsp数据到tag之间的入口。所以tag里面必须有一个setValue方法,具体的属性可以不叫value。例如setValue(String data){this.data = data;}。这个“value”的名称是在tld里定义的。取什么名字都可以,只需tag里提供相应的set方法即可。

2. 处理 doStartTag 或 doEndTag 。这两个方法是 TagSupport提供的。还是以c:out value=""/为例,当jsp解析这个标签的时候,在“<”处触发 doStartTag 事件,在“>”时触发 doEndTag 事件。通常在 doStartTag 里进行逻辑操作,在 doEndTag 里控制输出。

  在处理tag的时候:

  0. 从tagPool中取得对应tag。

1.     为该tag设置页面上下文。

2.     为该tag设置其父tag,如果没有就为null。

3.     调用setter方法传入标签属性值tag,如果该标签没有属性,此步跳过。

4.     调用doStartTag方法,取的返回值。

5.     如果该标签有body,根据doStartTag返回值确定是否pop该标签内容。如果要pop其body,则:setBodyContent(),在之后,doInitBody()。如果该标签没有body,此步跳过。

6.     调用doEndTag()以确定是否跳过页面剩下部分。

7.     最后把tag类返还给tagPool。

tag类为:

package my.customtags;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.PageContext;

import javax.servlet.jsp.tagext.TagSupport;

 

public class Hidden extends TagSupport{

    String name;  

    public Hidden(){    name = "";    }

    public void setName(String name){    this.name = name;    }

    public void release(){   value = null;    }

    public int doStartTag(){  return EVAL_BODY_INCLUDE;}

public int doEndTag() throws JspTagException{

   try{   pageContext.getOut().write(", you are welcome");   }

   catch(IOException ex){   throw new JspTagException("Error!");    }

   return EVAL_PAGE;

}

}

 

Jsp页面:

<my:hidden name="testname"/>

 

生成的jsp代码:

my.customtags.Hidden _jspx_th_my_hidden_11 = (my.customtags.Hidden) _jspx_tagPool_my_hidden_name.get(my.customtags.Hidden.class);

_jspx_th_my_hidden_11.setPageContext(pageContext);

_jspx_th_my_hidden_11.setParent(null);

_jspx_th_my_hidden_11.setName("testname");

int _jspx_eval_my_hidden_11 = _jspx_th_my_hidden_11.doStartTag();

if (_jspx_th_my_hidden_11.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)

   return true;

_jspx_tagPool_my_hidden_name.reuse(_jspx_th_my_hidden_11);

return false;

 

   Taglib技术提供两个机制,Body和non-Body导致了taglib的出现了两个分支:Display Tag和Control Tag, 前者在java code中嵌入了html标签,相当与一个web component,而后者则是另一种模板脚本。

 

四、两种技术方案的比较:

       1. 技术学习难易度

模板技术。使用模板技术,第一点就是必须学习模板语言,尤其是强控制的模板语言。于是模板语言本身的友好性变的尤为重要。以下依据友好性,表现力以及复用性三点为主基点比较了一下几种模板技术。

Velocity:

Turbine项目(http://jakarta.apache.org/Turbine)采用了velocity技术。

1.       友好性不够。理由: 强控制类型,出现页面显示控制代码和html混合。与Html的不兼容,无法所见即所得。遇到大的HTML页面,从一个 “#if”找到对应的 “#end”也是很痛苦的一件事情。

2.       表现力强。理由:强控制语言。

3.       复用性弱。理由:模板脚本和页面代码混合。

XSLT

Cocoon项目(http://cocoon.apache.org/)采用XML + XSLT的方法。优快云社区也是采用此方案。

1.       内容和显示风格分离,这点XSLT做的最好。

2.       速度慢。理由:XSLT的使用XPath,由于是要解析DOM树,当XML文件大时,速度很慢。

3.       友好性不够。理由:由于没有HTML文件,根本看不到页面结构、显示风格和内容。XSL语法比较难以掌握,由于没有“所见即所得”编辑工具,学习成本高。

4.       表现力强。理由:强控制语言。

5.       复用性弱。理由:xsl标签和html标签混合。

JDynamiTe

1.       表现力中等。理由:弱控制语言。

2.       友好性强。理由:所见即所得的效果。在模板件中的ignore block在编辑条件下可展示页面效果,而在运行中不会被输出。

3.       复用性强。理由:利用html标签。

Tapestry

1.       友好性中等。理由:整个Tapestry页面文件都是HTML元素。但是由于component会重写html标签,其显示的样子是否正确,将不预测。

2.       表现力强。理由:强控制语言。

3.       复用性强。理由:扩展了HTML元素的定义。

 

 

在JSP中大量的使用TagLib,能够使得JSP的页面结构良好,更符合XML格式,而且能够重用一些页面元素。但TagLib的编译之后的代码庞大而杂乱。TabLib很不灵活,能完成的事情很有限。TabLib代码本身的可重用性受到TagSupport定义的限制,不是很好。 另外是,我不得不承认的一件事是,TagLib的编写本身不是一件愉快的事情,事实我个人很反对这种开发方式。

 

       2. 技术使用难易度

       模板技术:模板技术本身脱离了Web环境,可以在不启动Web server得情况下进行开发和测试,一旦出错详细的信息易于错误的定位。由于模板引擎的控制,页面中将只处理显示逻辑(尽管其可能很复杂)

       JSP技术:工作在Web环境下,开发测试一定要运行web server。此外,一些TagLib能够产生新的标签,页面的最终布局也必须在web环境下才可以确定。测试时出错信息不明确,特别是TagLib得存在,极不容易定位。由于其本质是程序,很容易在其中写入业务逻辑,甚至于数据库连接代码,造成解耦的不彻底。

 

3. 总结

模板技术更加专注于页面的显示逻辑,有效帮助开发人员分离视图和控制器。在学习,开发和测试都更加容易。

JSP 技术本身是一个早期的技术,本身并没有提出足够的方式来分离视图和控制器。相反,我认为其本身是鼓励开发人员不做解耦,因为在 JSP 代码中插入业务逻辑是如此的容易。
jsp默认模板 做模板用, 立即下载

相关推荐

零基础教程:用Python给试卷照片自动切题(有道OCR+PIL完整流程)

本文为零基础用户提供了一套完整的Python自动化切题方案。通过调用有道OCR API识别试卷照片中的题目坐标,并利用PIL库进行精准裁剪,将杂乱的试卷图片自动分割为独立的题目图像。教程详细涵盖了环境搭建、图像预处理、API调用、坐标解析与批量处理全流程,帮助教育工作者和技术爱好者高效处理大量试卷,实现工作流程自动化。

grpc6streamer的博客 1174

jsp template之我见

我们在做程序的过程中,常常会遇到这样一种情况,就是在一个项目中,会发现有很多页面的框架基本相同的,只是具体显示的内容不同,而按常规的做法,我们可能会用include语句来提出框架内容,然后在每个页面中引用这些框架,但这样就会产生一个问题,如果我的框架发生变化了,那应该怎么办呢?举个例子,一个index.jsp可能包含有head.jsp和foot.jsp。而其它页面也同样包含这两个JSP。但如果我在

jeff技术博客 2812

MC1496乘法器AM调制电路搭建全流程(附Multisim 14.0仿真文件)

本文提供了基于MC1496乘法器搭建AM调制电路的完整实战指南。针对仿真模型缺失的痛点,详细讲解了从晶体管级手动构建MC1496等效模型,到外围电路设计、调制度参数计算与调节,并在Multisim 14.0中进行仿真验证的全流程。通过深度剖析MC1496内部原理与AM信号调制机制,帮助读者获得从仿真到实践的可控设计与排错能力。

weixin_29190169的博客 593

JSP模板应用指南(上)

Window 工具包提供了一种典型的布局机制,比如说在一个容器中确定部件元素的位置。在AWT 和 Swing都有布局管理器,而在VisualWorks Smalltalk中有wrapper。本文将介绍一种JSP模板机制,它允许布局被封装和重新利用。JSP模板最小化了布局改变所造成的影响,这里我们将鼓励大家采用封装模块化设计。   尽管 Web开发工具的改进非常迅速,但是它们仍然落后于图形

SAIN 696

ICG setup timing violation介绍?

门控时钟(clock gating)在RTL级电路设计过程中进行低功耗优化常用方法,能够有效降低动态功耗(翻转功耗)。Clock gating cell 可以由与门,与非门,或门或者或非门构成,但很容易产生Glitch。在实际使用中,一般用ICG(集成门控时钟单元)来完成clock gating。 下图展示了glitch的产生原因 在CTS时钟树综合的时候,ICG不会被看作sink,通常放置在source点附近,因此就会出现如上图这种结果。上图可以看出,在分析DFF到ICG的setup timing

m0_61003348的博客 9810

告别抓包失败!保姆级配置:让Burp+Proxifier稳定抓取任意微信小程序

本文提供了一套完整的Burp+Proxifier配置方案,确保稳定抓取微信小程序数据。从环境准备、工具选型到Burp Suite深度配置和Proxifier精准设置,详细解决了证书安装、进程捕获和乱码解析等核心问题,帮助开发者告别抓包失败,提升调试效率。

weixin_28738165的博客 455

springboot如何使用jsp/templates

一:如何使用jsp 1.springboot默认是不支持jsp的,要想用jsp的话,需要导一个插件,在pom.xml里添加依赖 &lt;dependency&gt; &lt;groupId&gt;org.apache.tomcat.embed&lt;/groupId&gt; &lt;artifactId&gt;tomcat-embed-jasper&lt;/artifactId&...

qq_43154385的博客 5020

手把手教你用Docker快速部署开源MES系统(附避坑指南)

本文提供了一份详细的实战指南,手把手教你使用Docker容器化技术快速部署开源MES系统。内容涵盖从环境准备、项目选型、数据库配置到应用服务器优化、前端部署及生产环境监控的全流程,并附有避坑指南,旨在帮助中小制造企业IT人员和开发者低成本、高效率地构建智能制造解决方案。

f0g1h2的博客 1063

使用jsp模板——template.js

附上github地址 用script圈出一部分区域,用来存放模板 注意 1、要有id2、type类型是text/html3、{{each list as value i}}圈出遍历范围4、{{value.xxx}}用来取值 <script id="goodStore" type="text/html"> {{each list as value i}} <div class="gs-

我给媳妇儿讲java 6114

EtherCAT同步模式实战:如何用TwinCAT配置DC-Synchronous模式(附时序图详解)

本文详细解析了如何在TwinCAT环境中配置EtherCAT的DC-Synchronous同步模式,实现纳秒级同步精度。通过硬件准备、参数配置和高级调优步骤,帮助工程师解决工业自动化中的同步挑战,提升运动控制性能。

gold的博客 1571

OpenClaw人人养虾:发现与传输

客户端需要先"发现"Gateway 的地址和端口,才能建立连接。OpenClaw 支持多种发现(Discovery)和传输(Transport)机制。

王国平的博客 572

jsp:attribute

在传统 JSP 中,想要实现页面布局管理比较麻烦,为了解决在 JSP 中布局的问题,出现了很多开源软件,比如 Apache Tiles 和 SiteMesh 就是其中比较优秀的。但是使用开源软件实现布局或多或少会产生一些性能问题,有没有办法在不依赖第三方开源软件的情况下,使用 JSP 本身来实现页面布局呢?JSP 2.0 引入了 Fragment 技术,使用 Fragment 技术可以在 JSP...

weixin_30781433的博客 224

GB28181 —— 1、Ubuntu20.04下使用ZLMediaKit+WVP搭建GB28181流媒体监控平台(连接带云台摄像机)

GB28181 —— Ubuntu20.04下使用ZLMediaKit+WVP搭建GB28181流媒体监控平台

5461

<jsp:invoke fragment=""/>的理解和使用

本文出自:http://www.tuicool.com/articles/ERFZvyy 在传统 JSP 中,想要实现页面布局管理比较麻烦,为了解决在 JSP 中布局的问题,出现了很多开源软件,比如 Apache Tiles 和 SiteMesh 就是其中比较优秀的。但是使用开源软件实现布局或多或少会产生一些性能问题,有没有办法在不依赖第三方开源软件的情况下,使用 JSP 本

537

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【Go语言开发实战】:为何你在Go中找不到JSP?彻底搞懂服务端模板技术选择

wu

FuncTide的博客 632

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

轻量级的代码生成方案选择

第3版--2005.6.22更新        上次说到MyAppfuse要有一个代码生成工具, codegeneration.net上汇集了各种平台各种语言的工具。    其实代码生成是和代码重复的bad smell一样古老的东西了,不过在这个时代里,大家充分发掘了继承,委托,反射,甚至AOP的之后,coding 依然boring,依然重复,这时候就需要从一个更抽象的层次去描述系统,然后再生成我

花钱的年华 8726

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Java利用技巧——通过反射实现webshell编译文件的自删除

0x00 前言 我们知道,当我们访问jsp文件时,Java环境会先将jsp文件转换成.class字节码文件,再由Java虚拟机进行加载,这导致了Java服务器上会生成对应名称的.class字节码文件。对于webshell,这会留下痕迹。 为了实现自删除.class字节码文件,我们可以通过反射获得.class字节码文件的路径,再进行删除。本文将以Zimbra环境为例,结合AntSword-JSP-Template,分析利用思路。 0x01 简介 本文将要介绍以下内容: 通过反射实现...

HongYu012的博客 635

struts-bean.tld,struts-html.tld,struts-logic.tld 文件的作用

struts-html标签库。这个库可以被用来生成动态HTML用户界面和窗体。 struts-bean标签库。在将JavaBean代码放入JSP   页面时这个库提供实质性的加强的功能以改善其性能,它由标签提供。 struts-logic标签库。这个库可管理有条件的文本生成,在对象集合中循环以重复生成输出文本和应用程序流程管理。 struts-template标签库。在为具有

小苟的专栏 1768

产生静态的hmtl文件

产生静态的hmtl文件 从publish.jsp开始执行,html.template是模板文件,publish.jsp提交给publishOK.jsp处理,生成静态的html文件! //html.template文件 &lt;html&gt;&lt;head&gt;&lt;meta http-equiv="Content-Type" content="text/html; charset=g...

编程资料大全 126

jspwiki Processor

Just record some I got. Organize it later *.jsp->*Template.jsp->Tag.java->get something in WikiContext.java ->get mass from PageCommand.java to get default configure

Heraclesun 141

模板技术相对传统JSP技术有以下三个主要优势

模板技术相对传统JSP技术有以下三个主要优势:1. 在技术层面,将表现逻辑与业务逻辑相分离。2. 为人员间的分工提供了一个良好的分界点。页面美工只需专著关心模板的设计,而程序员则专注于业务逻辑的实现。二者重合点明显减少。3. 如果需要,模板引擎可脱离Web 容器单独运行,这为系统可能的移植需求提供了更多的弹性空间(这一特性在应用中也许并不会有太大的实际意义,只是提供了一种附加选择)...

学习笔记 438
上一篇: MetaData Programme
下一篇: JVM,反射与动态代理
林仪明
博客等级 码龄25年 313粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值