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


1673

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

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

这是一种古老的编码方式,在JSP版本2中,存在一种避免在JSP文件中使用Java代码的方法。有人可以告诉我替代的JSP 2行吗,这种技术叫什么?


22
@Koray Tugay,只要在使用计数器变量之前就声明了该变量,那么它肯定是有效的……
Sheldon R.

@SheldonR。这是有效的:<%= counter ++%>或以下内容:<%!int计数器= 0; int x =计数器++; %>,但不:<%!int计数器= 0; 计数器++; %>
Koray Tugay

@KorayTugay,我的意思是,如果变量计数器是在较早的脚本块中声明的,则它应在较后的块中有效。但是最终,无论如何,这些天的J2EE程序员无论如何应该使用EL变量而不是脚本集……
Sheldon R.

Answers:


1971

自从标签库(例如JSTL)和EL表达语言,那些东西)的诞生可追溯到2001年以来,在JSP中确实不鼓励使用scriptlet(那些<% %>东西)。${}

scriptlet的主要缺点是:

  1. 可重用性:您无法重用scriptlet。
  2. 可替换性:您不能使scriptlet抽象。
  3. 面向对象的能力:您不能利用继承/组合。
  4. 可调试性:如果scriptlet中途抛出异常,则您得到的只是空白页面。
  5. 可测试性:脚本无法进行单元测试。
  6. 可维护性:每一次维护,需要花费更多时间来维护混杂/混乱/重复的代码逻辑。

Sun Oracle本身还建议在JSP编码约定中避免使用(标记)类可能具有相同功能的scriptlet。以下是一些相关的引用:

从JSP 1.2规范开始,强烈建议在您的Web应用程序中使用JSP标准标记库(JSTL),以帮助减少页面中对JSP scriptlet的需求。通常,使用JSTL的页面更易于阅读和维护。

...

只要有可能,只要标签库提供等效功能,就避免使用JSP scriptlet。这使页面更易于阅读和维护,有助于将业务逻辑与表示逻辑分离,并使您的页面更易于演变为JSP 2.0样式的页面(JSP 2.0规范支持但不强调脚本的使用)。

...

本着采用模型视图控制器(MVC)设计模式来减少表示层与业务逻辑之间的耦合的精神,不应将JSP脚本集用于编写业务逻辑。而是,如果有必要,可以使用JSP scriptlet将处理客户机的请求返回的数据(也称为“值对象”)转换为适当的客户机就绪格式。即使这样,最好还是使用前端控制器servlet或自定义标签来完成。


如何完全替换scriptlet取决于代码/逻辑的唯一目的。这段代码比以往更多地被放置在完全值得的Java类中:

  • 如果要在每个请求上调用相同的 Java代码,则无论请求页面是多少,都应或多或少地调用它,例如,检查用户是否登录,然后实现过滤器,并在方法中相应地编写代码。例如:doFilter()

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
            ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
        } else {
            chain.doFilter(request, response); // Logged in, just continue request.
        }
    }

    当映射到适当的<url-pattern>覆盖感兴趣的JSP页面时,则无需在整个JSP页面上复制粘贴同一段代码。


  • 如果要调用某些Java代码来预处理请求,例如,如果需要,则基于某些查询参数,从数据库中预加载一些列表以显示在某个表中,则可以实现servlet,并在doGet()方法中相应地编写代码。例如:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            List<Product> products = productService.list(); // Obtain all products.
            request.setAttribute("products", products); // Store products in request scope.
            request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
        } catch (SQLException e) {
            throw new ServletException("Retrieving products failed!", e);
        }
    }

    这种处理异常的方法比较容易。在JSP渲染过程中,不能访问DB,但是要在显示JSP之前就可以访问DB。每当数据库访问引发异常时,您仍然可以更改响应。在上面的示例中,将显示默认错误500页面,您可以通过<error-page>in对其进行自定义web.xml


  • 如果要调用一些Java代码来对请求进行后处理(例如,处理表单提交),请实现Servlet并相应地在doPost()方法中编写代码。例如:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);
    
        if (user != null) {
            request.getSession().setAttribute("user", user); // Login user.
            response.sendRedirect("home"); // Redirect to home page.
        } else {
            request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
            request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
        }
    }

    这种处理不同结果页面目标的方法更加容易:在出现错误的情况下重新显示带有验证错误的表单(在此特定示例中,您可以${message}EL中使用它重新显示它),或者在成功的情况下仅进入所需的目标页面。


  • 如果要调用一些Java代码来控制执行计划和/或请求和响应的目的地,则根据MVC的Front Controller Pattern实现servlet。例如:

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Action action = ActionFactory.getAction(request);
            String view = action.execute(request, response);
    
            if (view.equals(request.getPathInfo().substring(1)) {
                request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
            } else {
                response.sendRedirect(view);
            }
        } catch (Exception e) {
            throw new ServletException("Executing action failed.", e);
        }
    }

    或者只是采用MVC框架(如JSFSpring MVCWicket等等),这样就只需要JSP / Facelets页面和JavaBean类即可,而无需自定义servlet。


  • 如果要调用一些Java代码来控制 JSP页面内的流,则需要获取一个(现有的)流控制标记库,例如JSTL core。例如List<Product>在表格中显示:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    ...
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.name}</td>
                <td>${product.description}</td>
                <td>${product.price}</td>
            </tr>
        </c:forEach>
    </table>

    使用XML样式的标签非常适合所有HTML,与一堆带有各种开合和结束大括号的脚本(更好的可读性,因此可维护性)相比,代码更易读(“此结束大括号到底在哪里?”)。一种简单的帮助是将Web应用程序配置为在仍然使用scriptlet的情况下抛出异常,方法是将以下内容添加到web.xml

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

    Facelets的,JSP的继任者,它是Java EE的一部分提供的MVC框架JSF,它已经能够使用小脚本。这样,您将自动被迫以“正确的方式”做事。


  • 如果要调用某些Java代码来访问和显示 JSP页面内的“后端”数据,则需要使用EL(表达语言)之类的${}东西。例如,重新显示提交的输入值:

    <input type="text" name="foo" value="${param.foo}" />

    ${param.foo}显示器的结果request.getParameter("foo")


  • 如果要直接在JSP页面中调用一些实用 Java代码(通常是public static方法),则需要将它们定义为EL函数。JSTL中有一个标准函数taglib,但是您也可以轻松地自己创建函数。这是一个示例JSTL如何fn:escapeXml用于防止XSS 攻击

    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    ...
    <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />

    请注意,XSS敏感性与Java / JSP / JSTL / EL /无关,无论如何,在您开发的每个 Web应用程序中必须考虑到此问题。scriptlet的问题在于,它无法提供内置的预防措施,至少没有使用标准的Java API。JSP的继任者Facelets已经具有隐式HTML转义,因此您不必担心Facelets中的XSS漏洞。

也可以看看:


117
+1好答案。但是不要教条,有时使用scriptlet是可以的,但这应该是证明规则的例外。
svachon 2010年

26
@svachon:小脚本可用于快速原型制作/测试。据我所知,只有一种“合法”的生产脚本使用方式,即<% response.getWriter().flush(); %></head>和之间<body>改善脚本浏览器中的网页解析性能。但是,当服务器端的输出缓冲区大小较小(1〜2KB)时,此使用可以完全忽略。另请参阅本文
BalusC 2010年

5
@BalusC几次,我都被那些不遵循getter / setter模式的Java类所困扰。恕我直言,这是scripltet做这项工作的情况。
svachon 2010年

41
@svachon:我会用自己的javabean类包装这些类,并改用它们。
BalusC 2010年

31
这是一个很好的答案,但是doGet和doPost部分具有误导性。这些方法用于处理特定的请求(HEAD,GET和POST)方法,而不用于“预处理”或“后处理”请求!
MetroidFan2002 2012年

225

保障措施:永久禁用脚本

在讨论另一个问题时,您可以并且始终应该在web.xmlWeb应用程序描述符中禁用scriptlet 。

我将始终这样做,以防止任何开发人员添加scriptlet,尤其是在大型公司中,您迟早会失去概述。该web.xml设置是这样的:

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

4
这还会禁用scriptlet注释吗?:<%-- comment that i don't want in the final HTML --%>。我发现使用这些注释而不是HTML注释很有用。
大卫·拉文德

16
@MrSpoon为您找到了答案。根据此答案和注释,这将关闭scriptlet <% %>,scriptlet表达式<%! %>和scriptlet声明<%= %>。这意味着指令<%@ %>和注释<%-- --%>保持启用和可用状态,因此您仍然可以进行注释和包含。
马丁·卡尼

3
禁用scriptlet指令将是可怕的-修剪空白对于与遗留多余空白的旧式系统进行交互非常有价值。
corsiKa 2015年

108

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

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

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


2
为什么说JSTL可用于请求属性?它们可以在任何范围内使用属性,不是吗?
Koray Tugay 2014年

60

我不确定我是否正确。

您应该阅读有关MVC的内容。Spring MVCStruts 2是两个最常见的解决方案。


29
可以使用Servlet / jsp使用上述许多技术来实现MVC,而无需使用Spring或Struts。
stepanian '02

18
它如何回答这个问题?
xyz 2015年

54

可以将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>

34

还有一些基于组件的框架,例如Wicket,可以为您生成许多HTML。最终出现在HTML中的标签是非常基本的,几乎没有逻辑混入其中。结果是带有典型HTML元素的几乎像空的HTML页面。不利的一面是,Wicket API 中有很多组件需要学习,在这些限制下,有些事情可能很难实现。


33

在MVC体系结构模式中,JSP代表视图层。在JSP中嵌入Java代码被认为是不好的做法。您可以使用JSTLFreeMarker的速度与JSP作为“模板引擎”。这些标签的数据提供者取决于您正在处理的框架Struts 2webwork作为MVC模式的实现使用OGNL “非常有趣的技术暴露bean的属性给JSP”。


27

经验表明,JSP有一些缺点,其中之一就是很难避免将标记与实际代码混合在一起。

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


3
旧的答案,但我不禁要说JSF是Java空间中最恐怖的发明之一。尝试建立单个(类似于HTTP GET)链接,您将了解原因。
Alex

@Alex但还是更好。随时推荐更好的东西。
托尔比约恩Ravn的安徒生

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>

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>

尽管组件的可重用性很好,但它针对某些领域
tomasb 2011年

25

Wicket还是完全将Java与html分开的一种替代方法,因此设计人员和程序员可以一起工作,并且在彼此几乎不了解的情况下使用不同的代码集。

看小门。


23

您提出了一个很好的问题,尽管您得到了很好的答案,但我建议您摆脱JSP。过时的技术最终将消失。使用模板引擎等现代方法。您将业务层和表示层非常清楚地分开,并且模板中肯定没有Java代码,因此在大多数情况下,利用所见即所得,您可以直接从Web表示编辑软件生成模板。

并且一定要远离过滤器以及预处理和后期处理,否则您可能会遇到支持/调试难题,因为您始终不知道变量从何处获取值。


9
JSP本身就是模板引擎
WarFox 2011年

1
-1- 使用过滤器,预处理器和后处理器有许多完全正当的理由。是的,您最终可能会获得看似神秘的价值,但如果您了解自己的体系结构,则不会。
RustyTheBoyRobot 2012年

21

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


21

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

在您的WEB-INF / tags下创建一个名为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>

在此母版页上,我创建了一个名为“标题”的片段,以便在子页上可以将更多代码插入母版页的此位置。同样,标签<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/>您的母版页上的。您的子页面也可以包含任何标签库,您可以像上面提到的其他标签库一样正常使用它。但是,如果您在此处(<%= request.getParameter("name") %>...)使用任何scriptlet代码并尝试运行此页面,则将获得一个JasperException because Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here。因此,其他任何人都无法将邪恶代码包含在jsp文件中

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

您可以从控制器轻松调用child.jsp文件。这在struts框架中也很好用


“无论您试图避免多少,当您与其他开发人员一起工作时,其中一些仍然会喜欢scriptlet,然后将恶意代码插入项目中。” 请参阅“作为安全措施:永久禁用脚本”。
Lluis Martinez


18

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


17

如果有人真的反对使用一种以上的语言进行编程,我建议您使用GWT,从理论上讲,您可以避免使用所有JS和HTML元素,因为Google工具包将所有客户端代码和共享代码转换为JS,因此您不会遇到任何问题,因此您有一个没有使用任何其他语言编码的Web服务。甚至您也可以从扩展名(smartGWT或Vaadin)指定的位置使用某些默认CSS。您无需学习许多注释。

当然,如果愿意,您可以深入代码的深处,注入JS并丰富HTML页面,但实际上,如果愿意,可以避免使用它,其结果将是在任何其他框架中编写的。我说值得一试,基本的GWT有据可查。

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


1
并没有真正回答OP的问题。
Evan Donovan 2014年

1
@EvanDonovan很好,实际上它确实给出了答案。您无需将Java代码与其他语言混为一谈。我承认它使用Java进行编码,但无需Java调用即可将其转换为JS。但是问题的范围是如何避免经典JSP的混乱。而GWT技术解决了这一问题。由于没有人提及我,所以我加了这个答案,但由于它是JSP的替代品,所以很有意义。我不想回答这个问题的全部内容,而是为寻求替代方法的人添加有价值的信息。
CsBalazsHungary 2014年

16

Python世界的一个巧妙想法是模板属性语言 ; TAL是由Zope引入的(因此又称为“ 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实现并不了解很多。


1
自2009年12月以来,支持此功能的Facelets继承了JSP。Facelets也是基于XML的。另请参见Java EE 6教程Facelets章节ui:xxxFacelts VDL中的标签
BalusC 2012年

我不太了解Facelets,但是IIRC完全是关于编写实现自定义XML元素的类。TAL / ZPT方法是使模板包含包含特殊属性的true(X)HTML,这些属性填充或替换原始元素;因此,您可以查看工作模板并查看具有良好虚拟内容的原型。我不确定Facelets是否允许使用自定义属性来调整原始HTML元素(不包含其他名称空间)。
Tobias

我只是再看了一下Facelets上的东西。它包含各种验证工具等,因此遵循与TAL完全不同的理念。TAL的方式是:“将逻辑尽可能干净地保留在模板之外;让所有复杂的事情由提供模板的控制器完成。” 您永远不会将Facelets模板提供给设计师进行调整。只是不可能。关于生成的内容-就像一直使用tal:replace="structure (expression)"属性一样。
Tobias 2014年


14

确定,更换 <%! counter++; %>事件生产者-消费者体系结构,该体系结构将通知业务层需要增加计数器的信息,并相应地做出反应,并通知展示者,以便他们更新视图。涉及许多数据库事务,因为将来我们将需要知道计数器的新值和旧值,谁增加了计数器以及其目的是什么。显然,涉及序列化,因为这些层是完全解耦的。您将可以通过RMI,IIOP,SOAP来增加计数器。但是只有HTML是必需的,您不必实现,因为这是一种平凡的情况。您的新目标是在新的闪亮E7 64GB RAM服务器上达到每秒250个增量。

我从事编程已有20多年的经验,大多数项目在六重奏之前就失败了:可重用性可替换性OO能力可调试性可测试性甚至需要可维护性。由仅关心功能性的人员运行的其他项目非常成功。同样,在项目中实施得太早的硬对象结构使代码无法适应规范的急剧变化(又称敏捷)。

因此,我将在项目初期或在没有特别要求时定义“层”或冗余数据结构的活动视为拖延。  


11

从技术上讲,JSP会在运行时全部转换为Servlet。最初创建JSP是为了遵循MVC模式将业务逻辑和设计逻辑分离。因此,从技术上讲,JSP在运行时是所有Java代码。但是要回答这个问题,标签库通常用于将逻辑(删除Java代码)应用于JSP页面。


8

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

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

  2. 使用JSP标签

    一个。标准标签

    b。自定义标签

  3. 表达语言


8

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

您可以使用标签库标签,例如 除了表达式语言(EL)之外, JSTL之。但是EL在JSP中不能很好地工作。因此,最好完全删除JSP并使用Facelets更好。

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

在此处输入图片说明

资源


我肯定是第二反应。带有或不带有Facelets的JSF。我以为使用JSP进行开发已在10多年前停止了。我上一次在2000年编写了JSP!
行李箱'17

4

使用Scriptlets是一种非常古老的方法,不建议使用。如果要直接在JSP页面中输出某些内容,只需将Expression Language(EL)JSTL一起使用。

还有其他选择,例如使用模板引擎,例如Velocity,Freemarker,Thymeleaf等。但是大多数时候,使用带有EL和JSTL的纯JSP可以达到我的目的,而且对于初学者来说,这似乎是最简单的。

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


3

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

就我而言,我的系统使用Angular处理视图,所需的任何数据都通过使用rest服务从服务器中获取。

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


3

使用骨架,像javascript框架这样的角度进行UI设计,并使用rest api获取数据。这将从UI中完全删除Java依赖项。


3

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,access sessionrequest ...在你的标签文件了。

标签文件 非常容易开发,因为更改它们时无需像JSP文件那样重新启动服务器。这使它们易于开发。

即使您使用诸如Struts 2这样的框架,该框架具有许多好的标签,您可能会发现拥有自己的标签可以大大减少代码。您可以将标签参数传递给struts,这样可以自定义框架标签。

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

(即使您最终在JSP代码中使用Java,但我希望不要在Java代码中使用Java,您也可以将该代码封装在标签中)


1

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


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

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


0

通过将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" %>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.