如何避免使用JSP 2在JSP文件中Java代码?

我刚JavaEE,我知道下面三行

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

是一种老派的编码方式,在JSP版本2中存在一种避免在JSP文件中Java代码的方法。

312133 次浏览

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

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

JSTL使用请求属性——它们通常由Servlet在请求中设置,Servlet向前到JSP。

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

如果可以,那么考虑使用专门的技术来完成您需要做的事情。在JavaEE 6中有JSF 2.0,它提供了许多不错的特性,包括通过#{bean.method(argument)}方法将Javabean与JSF页面粘合在一起。

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

<%@ 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>

JSP中使用脚本(那些<% %>的东西)确实是非常不鼓励的,因为taglibs(像JSTL)和EL表达语言,那些${}的东西)早在2001年就诞生了。

脚本的主要缺点是:

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

Sun Oracle本身也在JSP编码约定中建议避免使用脚本,只要(标签)类可以实现相同的功能。以下是几个相关的引用:

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

在可能的情况下,只要标签库提供等效的功能,避免JSP脚本就会。这使得页面更易于阅读和维护,有助于将业务逻辑与表示逻辑分开,并使您的页面更容易演变成JSP 2.0风格的页面(JSP 2.0规范支持但不强调脚本的使用)。

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


如何替换scriptlet完全取决于代码/逻辑的唯一目的。此代码通常被放置在一个完整的Java类中:

  • 如果您想在请求上调用相同Java代码,无论请求的页面是多少,例如检查用户是否登录,然后实现过滤器并在#0方法中相应地编写代码。例如:

      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.}}

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


  • 如果你想调用一些Java代码到处理一个GET请求,例如从数据库中预加载一些列表以显示在一些表中,如果需要基于一些查询参数,然后实现servlet并在#0方法中相应地编写代码。例如:

      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渲染过程中访问的,而是在JSP显示之前很久。每当数据库访问抛出异常时,您仍然可以更改响应。在上面的例子中,将显示默认的错误500页面,您可以通过web.xml中的<error-page>进行自定义。


  • 如果你想调用一些Java代码到处理POST请求,例如从提交的超文本标记语言表单中收集数据并用它做一些业务操作(转换、验证、保存在数据库中等),然后实现servlet并在#0方法中相应地编写代码。例如:

      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.}}

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


  • 如果你想调用一些Java代码来控制执行计划和/或请求和响应的目的地,然后根据MVC的前端控制器模式实现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 mvc检票口等,这样您最终就只有一个JSP/Facelets页面和一个JavaBean类,而不需要自定义servlet。


  • 如果您想在JSP页面中调用一些Java代码控制流量,那么您需要获取一个(现有的)流控件taglib,如JSTL核心。例如。在表中显示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样式的标记(非常适合所有超文本标记语言),代码的可读性更好(因此更好的可维护性),而不是一堆带有各种开始和结束大括号的scriptlet(“这个闭合支架到底属于哪里?”)。一个简单的帮助是将您的Web应用程序配置为在脚本仍在使用时抛出异常,方法是将以下部分添加到web.xml

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

    Facelets中,JSP的继任者,它是JavaEE提供的MVC框架JSF的一部分,已经可以使用脚本了。这样你就自动被迫以“正确的方式”做事。


  • 如果您想在JSP页面中调用一些Java代码来访问和显示“后端”数据,那么您需要使用EL(表达式语言),那些${}的东西。例如。重新显示提交的输入值:

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

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


  • 如果您想直接在JSP页面中调用一些效用Java代码(通常是public static方法),那么您需要将它们定义为EL函数。JSTL中有标准的函数taglib,但您也可以轻松地自己创建函数。下面是一个JSTLfn: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/whatever没有任何特别关系,这个问题需要在您开发的 Web应用程序中考虑。脚本的问题是它没有提供内置预防方法,至少没有使用标准的JavaAPI。JSP的后续Facelets已经隐式超文本标记语言转义,所以您不必担心Facelets中的XSS漏洞。

另见:

在MVC架构模式中,JSP代表视图层。在JSP中嵌入Java代码被认为是一种不好的做法。

您可以将JSTLFreeMarker速度与JSP一起用作“模板引擎”。

Struts 2和功课输送系统作为MVC模式的实现使用OGNL“非常有趣的技术将Beans属性公开给JSP”。

为了避免在JSP文件中Java代码,Java现在提供了标记库,如JSTL。

此外,Java提出了JSF,您可以将所有编程结构以标记的形式写入其中。

还有一些基于组件的框架,例如检票口,可以为您生成大量超文本标记语言。

最终出现在超文本标记语言中的标签非常基本,几乎没有混合的逻辑。结果是几乎是空的超文本标记语言页面,具有典型的超文本标记语言元素。缺点是检票口 API中有很多组件需要学习,在这些限制下很难实现一些事情。

检票口也是一种将Java与超文本标记语言完全分离的替代方案,因此设计人员和程序员可以在彼此几乎不了解的情况下一起工作并处理不同的代码集。

看看Wicket

在JSP中使用JSTL标记库。这将完美地工作。

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

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

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

作为保障措施:永远禁用Scriptlet

正如另一个问题所讨论的,您可以并且应该始终禁用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>

学习使用JSTL自定义和编写自己的标签

请注意,EL是evl(运行时异常和重构)。

Wicket也可能是邪恶的(对于小型应用程序或简单的视图层,性能和麻烦)。

示例java2s

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

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

/WEB-INF/中创建文件java2s.tld

<!DOCTYPE taglibPUBLIC "-//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-在F\类\com\java 2 s

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());elseout.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>

如果我们在JavaWeb应用程序中使用以下内容,Java代码可以从JSP文件的前景中删除。

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

  2. 使用JSP标签

a.标准标签

b.定制标签

  1. 表达语言

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %><% // Instantiate a JSP controllerMyController clr = new MyController(request, response);
// Process action, if anyclr.process(request);
// Process page forwarding, if necessary
// Do all variable assignment hereString 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>

来自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>

代码看起来像普通的超文本标记语言(或XHTML)加上XML命名空间中的一些特殊属性;它可以用浏览器查看,并由设计人员安全地进行调整。

还有对宏和国际化和本地化的支持:

<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实施了解不多。

如果有人真的反对用多种语言编程,我建议GWT。理论上,你可以避免所有的JavaScript和超文本标记语言元素,因为谷歌工具包将所有的客户端和共享代码转换为JavaScript。你不会有问题,所以你有一个没有任何其他语言编码的网络服务。你甚至可以从某个地方使用一些默认的CSS,因为它是由扩展给出的(智能GWT或Vaadin)。你不需要学习几十个注释。

当然,如果你愿意,你可以深入到代码的深处,注入JavaScript并丰富你的超文本标记语言页面,但如果你愿意,你真的可以避免它,结果会像在任何其他框架中编写的一样好。

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

无论你如何努力避免,当你与其他开发人员合作时,他们中的一些人仍然会喜欢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>

在这个母版页上,我创建了一个名为“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/>。您的子页面也可以包含任何标签库,您可以像前面提到的那样正常使用它。但是,如果您在这里使用任何脚本代码(<%= 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文件

从技术上讲,JSP在运行时都转换为Servlet

JSP最初是为了按照MVC模式解耦业务逻辑和设计逻辑而创建的。因此,JSP在运行时技术上完全Java代码。

但是为了回答这个问题,标签库通常用于将逻辑(删除Java代码)应用于JSP页面。

在JSP中使用scriptlet不是一个好的做法。

相反,您可以使用:

  1. JSTL标签
  2. EL表达式
  3. 自定义标签-您可以定义要使用的自己的标签。

请参考:

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

当然,用事件生产者-消费者架构替换<%! counter++; %>,其中业务层被通知需要增加计数器,它相应地做出反应,并通知演示者,以便他们更新视图。涉及许多数据库事务,因为将来我们需要知道计数器的新旧值,谁增加了它,以及出于什么目的。显然涉及序列化,因为这些层是完全解耦的。你将能够在RMI、IIOP、SOAP上增加计数器。但只需要超文本标记语言,你不实现,因为它是如此平凡的情况。您的新目标是在新的闪亮的E7 64GB RAM服务器上每秒达到250个增量。

我从事编程20多年,大多数项目在六组之前就失败了:

因此,我认为在项目早期或不需要时定义“层”或冗余数据结构的活动是拖延。

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

除了表达式语言(EL)之外,您还可以使用像JSTL这样的制表符库标记。但是EL不能很好地与JSP一起工作。所以最好完全放弃JSP并使用Facelets

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

在此输入图片描述

来源

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这样的框架,它有很多好的标签,您也可能会发现拥有自己的标签可以大大减少您的代码。您可以将标签参数传递给strut,这样就可以自定义您的框架标签。

使用标记不仅可以避免Java,还可以最小化超文本标记语言代码。我自己尝试查看超文本标记语言代码,并在看到代码重复出现在我的页面时立即构建标签。

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

通过将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" %>

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

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

还有其他选项,例如使用模板引擎,例如VelSpeed、Freemarker、Thymeleaf等,但是使用带有EL和JSTL的普通JSP在大多数情况下可以满足我的目的,对于初学者来说似乎也是最简单的。

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

我的朋友,我的建议是将视图(CSS、超文本标记语言、JavaScript等)与服务器分离。

在我的情况下,我使用Angular处理我的系统,并且使用REST服务从服务器带来所需的任何数据。

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

使用Backbone.js或类似AngularJS的JavaScript框架进行UI设计并使用REST API获取数据。这将完全从UI中删除Java依赖项。

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

这种方法的好处是您的代码也是超文本标记语言代码!

这里的很多答案都是“使用框架”路线。这没有错。然而,我不认为它真的回答了你的问题,因为框架可能使用也可能不使用JSP,它们也没有以任何方式将删除JSP中的java使用作为主要目标。



这就是JSP的用途——使用Java来呈现具有动态数据/逻辑的超文本标记语言。接下来的问题可能是,我应该在我的JSP中使用多少java。在我们回答这个问题之前,你还应该思考,“我需要使用JSP来使用Java构建Web内容吗?”最后一个问题的答案是,不。使用Java开发面向Web的应用程序有很多JSP的替代方案。例如,Struts不会强迫你使用JSP——不要误会我,你可以使用它们,许多实现都可以,但你并不是绝对必须这样做。Struts甚至不会强迫你使用任何超文本标记语言。JSP也不是,但老实说,JSP不产生超文本标记语言有点奇怪。众所周知,Servlet允许您通过HTTP动态提供您喜欢的任何类型的内容。它们是几乎所有Java Web背后的主要技术-JSP只是servlet的超文本标记语言模板,真的。
因此,关于你应该在JSP中放入多少java的答案是“尽可能少”。我的JSP中当然有java,但它完全由标签库定义、会话和客户端变量以及封装服务器端对象的bean组成。我的超文本标记语言中的<%%>标签几乎完全是属性调用或变量表达式。罕见的例外包括与单个页面相关的超特定计算,不太可能被重用;由页面特定问题引起的错误修复仅适用于一个页面;最后一分钟的连接和算术来自于限制在单个页面范围内的异常要求;以及其他类似的情况。在150万行,3000个JSP和5000个类的代码集中,可能有100个这样独特的代码片段。在类或标记库定义中进行这些更改是完全可能的,但是由于每个案例的特殊性,它会变得异常复杂,编写和调试所需的时间更长,并且需要更多的时间才能到达我的用户。这是一个判断电话。但不要搞错,你不能在“没有java”的情况下编写任何意义的JSP,你也不想这样做。这种能力的存在是有原因的。

Java本身是一种非常好的语言,但在企业环境中的大量使用使其标准解决方案变得非常(荒谬)困难。例如:JSTL、JSF、Wicket等。

以下是在Java中创建后端的超轻量级方法:

  • 根本不使用JSP(或任何其他模板引擎);
  • 使用纯超文本标记语言模板;
  • 使用JSOUP将超文本标记语言模板解析为Document对象;
  • 使用其非常直观的类似jQuery的方法修改Document对象;
  • 返回Document.toString()作为对请求的响应。

我将它用于我的一个副项目(托管DigitalOcean 5美元的droplet,Nginx,Tomcat),它非常快:根据Googlebot的平均响应时间约为160毫秒。