如何避免JSP文件中的Java代码?

时间:2010-07-05 07:24:07

标签: java jsp scriptlet

我是Java EE的新手,我知道类似以下三行的内容

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

是一种旧式的编码方式,在JSP版本2中,存在一种避免JSP文件中的Java代码的方法。有人可以告诉我替代的JSP 2行,以及这种技术的名称是什么?

31 个答案:

答案 0 :(得分:1927)

答案 1 :(得分:218)

作为安全措施:禁用Scriptlets for Good

正如another question所讨论的那样,您可以并且始终应该在web.xml Web应用程序描述符中禁用scriptlet。

我总是这样做是为了防止任何开发人员添加scriptlet,尤其是在大型公司中,您迟早会丢失概述。 web.xml设置如下所示:

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
     <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>

答案 2 :(得分:106)

JSTL为条件,循环,集合,获取等提供标签。例如:

<c:if test="${someAttribute == 'something'}">
   ...
</c:if>

JSTL使用请求属性 - 它们通常由Servlet在请求中设置,转发到JSP。

答案 3 :(得分:60)

我不确定我是否认为这是正确的。

您应该阅读有关MVC的内容。 Spring MVC&amp; Struts 2是两种最常见的解决方案。

答案 4 :(得分:53)

您可以将JSTL标记与EL表达式一起使用,以避免混合使用Java和HTML代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
    <head>
    </head>
    <body>

        <c:out value="${x + 1}" />
        <c:out value="${param.name}" />
        // and so on

    </body>
</html>

答案 5 :(得分:34)

还有基于组件的框架,例如 Wicket ,可以为您生成大量HTML。最终在HTML中的标签非常基本,并且几乎没有混合的逻辑。结果几乎是空的HTML页面,具有典型的HTML元素。缺点是 Wicket API中有很多组件需要学习,有些事情在这些限制条件下很难实现。

答案 6 :(得分:32)

在MVC架构模式中,JSP表示View层。在JSP中嵌入Java代码被认为是一种不好的做法。 您可以将JSTLfreeMarkervelocity与JSP一起用作“模板引擎”。 这些标记的数据提供者取决于您正在处理的框架Struts 2webwork作为MVC模式的实现使用OGNL“非常有趣的技术将Beans Properties暴露给JSP”。

答案 7 :(得分:27)

经验表明,JSP有一些缺点,其中一个难以避免将标记与实际代码混合。

如果可以,请考虑使用专门的技术来满足您的需求。在Java EE 6中有JSF 2.0,它提供了许多不错的功能,包括通过#{bean.method(argument)}方法将Java bean与JSF页面粘合在一起。

答案 8 :(得分:26)

如果您只是想避免JSP中Java编码的缺点,即使使用scriplet也可以这样做。只需遵循一些规则,在JSP中使用最少的Java,而在JSP页面中几乎没有计算和逻辑。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%//instantiate a JSP controller
MyController clr = new MyController(request, response);

//process action if any
clr.process(request);

//process page forwaring if necessary

//do all variable assignment here
String showMe = clr.getShowMe();%>

<html>
    <head>
    </head>
    <body>
        <form name="frm1">
            <p><%= showMe %>
            <p><% for(String str : clr.listOfStrings()) { %>
            <p><%= str %><% } %>

            // and so on   
        </form>
    </body>
</html>

答案 9 :(得分:26)

了解如何使用JSTL自定义和编写自己的代码

请注意,EL是 EviL (运行时异常,重构)
Wicket也可能是邪恶的(性能,对于小应用程序或简单的视图层来说很麻烦)

示例来自 java2s

必须将其添加到Web应用程序的web.xml

<taglib>
    <taglib-uri>/java2s</taglib-uri>
    <taglib-location>/WEB-INF/java2s.tld</taglib-location>
</taglib>

在/ WEB-INF /

中创建File:java2s.tld
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<!-- a tab library descriptor -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>Java2s Simple Tags</short-name>

    <!-- this tag manipulates its body content by converting it to upper case
    -->
    <tag>
        <name>bodyContentTag</name>
        <tag-class>com.java2s.BodyContentTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
          <name>howMany</name>
        </attribute>
    </tag>
</taglib>

将以下代码编译为WEB-INF \ classes \ com \ java2s

package com.java2s;

import java.io.IOException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class BodyContentTag extends BodyTagSupport{
    private int iterations, howMany;

    public void setHowMany(int i){
        this.howMany = i;
    }

    public void setBodyContent(BodyContent bc){
        super.setBodyContent(bc);
        System.out.println("BodyContent = '" + bc.getString() + "'");
    }

    public int doAfterBody(){
        try{    
            BodyContent bodyContent = super.getBodyContent();
            String bodyString  = bodyContent.getString();
            JspWriter out = bodyContent.getEnclosingWriter();

            if ( iterations % 2 == 0 ) 
                out.print(bodyString.toLowerCase());
            else
                out.print(bodyString.toUpperCase());

            iterations++;
            bodyContent.clear(); // empty buffer for next evaluation
        }
        catch (IOException e) {
            System.out.println("Error in BodyContentTag.doAfterBody()" + e.getMessage());
            e.printStackTrace();
        } // end of catch

        int retValue = SKIP_BODY;

        if ( iterations < howMany ) 
            retValue = EVAL_BODY_AGAIN;

        return retValue;
    }
}

启动服务器并在浏览器中加载bodyContent.jsp

<%@ taglib uri="/java2s" prefix="java2s" %>
<html>
    <head>
        <title>A custom tag: body content</title>
    </head>
    <body>
        This page uses a custom tag manipulates its body content.Here is its output:
        <ol>
            <java2s:bodyContentTag howMany="3">
            <li>java2s.com</li>
            </java2s:bodyContentTag>
        </ol>
    </body>
</html>

答案 10 :(得分:25)

Wicket也是一种完全将java与html分开的替代方案,因此设计人员和程序员可以在不同的代码集上协同工作,而彼此之间几乎没有相互理解。

看看Wicket。

答案 11 :(得分:24)

你提出了一个很好的问题,虽然你得到了很好的答案,但我建议你摆脱JSP。它是过时的技术,最终会死亡。使用现代方法,如模板引擎。您将清楚地分离业务层和表示层,当然模板中没有Java代码,因此您可以直接从Web演示文稿编辑软件生成模板,在大多数情况下可以利用WYSIWYG。

当然要远离过滤器以及前后处理,否则你可能会遇到支持/调试困难,因为你总是不知道变量的值在哪里。

答案 12 :(得分:21)

为了避免JSP文件中的java代码,java现在提供了像JSTL这样的标记库,java也提出了JSF,你可以用标签的形式编写所有的编程结构

答案 13 :(得分:21)

无论你多少尝试避免,当你与其他开发人员合作时,他们中的一些人仍然会喜欢scriptlet,然后将邪恶的代码插入到项目中。因此,如果您真的想减少scriptlet代码,那么在第一个符号设置项目非常重要。有几种技术可以克服这个问题(包括其他提到的几个框架)。但是,如果您更喜欢纯JSP方式,那么请使用JSTL标记文件。关于这一点的好处是您还可以为项目设置母版页,以便其他页面可以继承母版页

在您的WEB-INF /标签下创建一个名为base.tag的母版页,内容如下

<%@tag description="Overall Page template" pageEncoding="UTF-8"%>

<%@attribute name="title" fragment="true" %>

<html>
  <head>
    <title>  
       <jsp:invoke fragment="title"></jsp:invoke>
    </title>

  </head>
  <body>
    <div id="page-header">
       ....
    </div>
    <div id="page-body">
      <jsp:doBody/>
    </div>
    <div id="page-footer">
      .....
    </div>
  </body>
</html>

在这个mater页面上,我创建了一个名为“title”的片段,这样在子页面中,我可以在母版页的这个位置插入更多代码。此外,标记<jsp:doBody/>将替换为子页面的内容

在WebContent文件夹中创建子页面(child.jsp):

  
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:base>
    <jsp:attribute name="title"> 
        <bean:message key="hello.world" />
    </jsp:attribute>

    <jsp:body>
    [Put your content of the child here]
    </jsp:body>   
</t:base>

<t:base>用于指定您要使用的母版页(此时为base.tag)。此处代码<jsp:body>内的所有内容都将替换您母版页上的<jsp:doBody/>。您的子页面还可以包含任何标记库,您可以像通常提到的那样使用它。但是,如果您在此处使用任何scriptlet代码(<%= request.getParameter("name") %> ...)并尝试运行此页面,您将获得JasperException because Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here。因此,其他人无法将恶意代码包含在jsp文件中

从您的控制器调用此页面:

您可以从控制器轻松调用child.jsp文件。这也适用于struts框架

答案 14 :(得分:19)

在JSP中使用 JSTL Tag libraries ,这将非常有效。

答案 15 :(得分:18)

只需使用JSTL标记和EL表​​达式。

答案 16 :(得分:17)

如果有人真的反对使用多种语言编程,我建议使用GWT,理论上你可以避免使用所有JS和HTML元素,因为Google Toolkit会将所有客户端和共享代码转换为JS,你不会遇到问题,所以你有一个没有任何其他语言编码的web服务。即使你可以使用某些默认的CSS,因为它是由扩展(smartGWT或Vaadin)提供的。您不需要学习几十个注释。

当然,如果你愿意的话,你可以深入了解代码的深度并注入JS并丰富你的HTML页面,但是你真的可以避免它,如果你想要的话,结果会很好,因为它写在任何其他框架。我说值得一试,基本的GWT已经有了很好的记录。

当然,许多程序员在此描述或推荐了其他几种解决方案。 GWT适用于那些真正不想处理Web部件或将其最小化的人。

答案 17 :(得分:16)

来自Python世界的一个巧妙的想法是模板属性语言; TAL由Zope引入(因此a.k.a。“Zope页面模板”,ZPT)并且是标准的,并且还实现了PHP,XSLT和Java(我使用了Python / Zope和PHP化身)。在这类模板语言中,上面的一个示例可能如下所示:

<table>
    <tr tal:repeat="product products">
        <td tal:content="product/name">Example product</td>
        <td tal:content="product/description">A nice description</td>
        <td tal:content="product/price">1.23</td>
    </tr>
</table>

代码看起来像普通的HTML(或XHTML)以及XML命名空间中的一些特殊属性;它可以通过浏览器查看,并由设计师安全地进行调整。 支持宏和i18n:

<h1 i18n:translate="">Our special offers</h1>
<table>
    <tr tal:repeat="product products">
        <td tal:content="product/name"
            i18n:translate="">Example product</td>
        <td tal:content="product/description"
            i18n:translate="">A nice description</td>
        <td tal:content="product/price">1.23</td>
    </tr>
</table>

如果内容的翻译可用,则使用它们。

但我对Java implementation并不是很了解。

答案 18 :(得分:15)

在JSP中使用scriptlet不是一个好习惯。

相反,您可以使用:

  1. JSTL标签
  2. EL表达式
  3. 自定义标签 - 您可以定义自己的标签以供使用。
  4. 请参阅:

    1. http://docs.oracle.com/javaee/1.4/tutorial/doc/JSTL3.html
    2. EL

答案 19 :(得分:14)

答案 20 :(得分:11)

从技术上讲,JSP在运行时都会转换为Servlet 。 JSP最初是为了按照MVC模式解耦业务逻辑和设计逻辑而创建的。所以JSP在运行时在技术上都是java代码。但回答这个问题,Tag Libraries通常用于将逻辑(删除Java代码)应用于JSP页面。

答案 21 :(得分:9)

如果我们在java Web应用程序中使用以下内容,则可以从JSP的前台删除java代码。

  1. 将MVC架构用于Web应用程序

  2. 使用JSP标记

    一个。标准标签

    湾自定义标签

  3. 表达语言

答案 22 :(得分:6)

如何避免JSP文件中的Java代码?

除了表达式语言( EL )之外,您还可以使用 JSTL 等标签库标签。但是EL与JSP不兼容。因此,最好完全删除JSP并使用 Facelets

Facelets 是第一个为 JSF(Java Server Faces)设计的非JSP页面声明语言,与JSP相比,它为JSF开发人员提供了更简单,更强大的编程模型。它解决了JSP中用于Web应用程序开发的不同问题。

enter image description here

Source

答案 23 :(得分:4)

使用Scriptlet是一种非常古老的方式,不推荐使用。如果您想在JSP页面中直接输出内容,只需使用表达式语言(EL)以及 JSTL

还有其他选项,例如使用模板引擎,如Velocity,Freemarker,Thymeleaf等。但是使用带有EL和JSTL的普通JSP大部分时间都是我的目的,对初学者来说似乎也是最简单的。

另外,请注意,在视图层中执行业务逻辑不是最佳做法,您应该在服务层执行业务逻辑, 并通过Controller将输出结果传递给您的视图。

答案 24 :(得分:3)

我的朋友不再使用这个,我的建议是将视图(css,html,javascript等)与服务器分离。

在我的情况下,我使用Angular处理视图,并使用其他服务从服务器获取所需的任何数据。

相信我,这将改变你的设计方式

答案 25 :(得分:3)

使用骨架(如javascript框架)进行UI设计 并使用rest api获取数据。这将从UI中完全删除Java依赖项。

答案 26 :(得分:2)

JSP 2.0有一个名为“标记文件”的功能,您可以编写没有外部java代码和tld的标记。您需要创建一个.tag文件并将其放在WEB-INF\tags中,您甚至可以创建一个目录结构来打包您的标记。

例如:

/WEB-INF/tags/html/label.tag

<%@tag description="Rensders a label with required css class" pageEncoding="UTF-8"%>
<%@attribute name="name" required="true" description="The label"%>

<label class="control-label control-default"  id="${name}Label">${name}</label>

一样使用它
<%@ taglib prefix="h" tagdir="/WEB-INF/tags/html"%>
<h:label  name="customer name" />

此外,您可以轻松阅读标签正文

/WEB-INF/tags/html/bold.tag
<%@tag description="Bold tag" pageEncoding="UTF-8"%>
<b>
  <jsp:doBody/>
</b>

使用它

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/bold"%>
<h:bold>Make me bold</h:bold>

样本非常简单,但您可以在这里完成许多复杂的任务。请考虑您可以使用其他标记(例如:JSTL具有控制标记,如if/forEcah/chosen文本操作,如format/contains/uppercase或甚至SQL标记select/update),传递所有类型参数,示例Hashmap,也可以在您的代码文件中访问sessionrequest,....

标记文件非常容易开发,因为您在更改服务器时不需要重新启动服务器,例如JSP文件。这使它们易于开发。

即使你使用像Struts 2这样的框架,它有很多好的标签,你可能会发现拥有自己的标签可以减少你的代码。您可以将标记参数传递给struts,这样就可以自定义框架标记。

您不仅可以使用标记来避免使用Java,还可以最小化HTML代码。一旦看到代码重复在我的页面中开始,我自己就会尝试查看HTML代码并构建标签。

(即使你最终在你的JSP代码中使用java,我希望不会,你可以将该代码封装在标签中)

答案 27 :(得分:1)

正如许多答案所说,使用JSTL或创建自己的自定义标签。 Here是关于创建自定义标记的很好的解释

答案 28 :(得分:1)

  1. 将值和参数包含在servlet类中
  2. 使用JSTL / Taglib在JSP中获取这些值和参数
  

这种方法的好处是您的代码也像HTML   代码!

答案 29 :(得分:0)

这里的许多答案都是“使用框架”路线。零错。但是,我认为这并不能真正回答您的问题,因为框架可能会也可能不会使用JSP,也没有以消除JSP中的Java使用为主要目标来设计框架。

您的问题“如何避免在JSP中使用Java”的唯一好答案是:您不能。

这就是JSP的目的-使用Java渲染具有动态数据/逻辑的HTML。 后续问题可能是,我应该在JSP中使用多少Java。
在回答该问题之前,您还应该考虑:“我需要使用JSP来使用Java来构建Web内容吗?”最后一个答案是,不。使用Java开发面向Web的应用程序时,有许多JSP替代方法。例如,Struts不会强迫您使用JSP-别误会,您可以使用它们,许多实现都可以使用,但是您不一定必须这样做。 Struts甚至不强迫您使用任何HTML。 JSP也不是,但是说实话,没有HTML的JSP有点奇怪。众所周知,Servlet使您可以通过HTTP动态提供您喜欢的任何类型的内容。它们是几乎所有Java Web背后的 主要技术-实际上,JSP只是Servlet的HTML模板。
因此,应该在JSP中放入多少Java的答案是“尽可能少”。我的JSP中当然有Java,但是它完全由标记库定义,会话和客户端变量以及封装服务器端对象的Bean组成。 HTML中的<%%>标记几乎完全是属性调用或变量表达式。罕见的例外情况包括与单个页面有关的超特定计算,不太可能重复使用;源自页面特定问题的错误修正,仅适用于一页;由于异常要求而导致的最后一刻的连接和算术,其范围仅限于一页;和其他类似情况。在150万行,3000个JSP和5000个类的代码集中,可能有100个这样的独特代码片段的实例。可以在类或标记库定义中进行这些更改,但是由于每种情况的特殊性,编写和调试需要更长的时间以及花更多的时间才能到达我的位置,所以它可能会变得异常复杂。用户。这是一个判断电话。但是请不要误解,您不能用“ no java”编写任何含义的JSP,也不想这样做。该功能存在是有原因的。

答案 30 :(得分:-1)

通过将JSTL标记与EL表达式一起使用,您可以避免这种情况。在jsp页面中添加以下内容:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>