提问人:chmoelders 提问时间:7/5/2010 最后编辑:starballchmoelders 更新时间:1/3/2023 访问量:318108
如何使用 JSP 2 避免 JSP 文件中的 Java 代码?
How can I avoid Java code in JSP files, using JSP 2?
问:
我知道像下面三行这样的东西
<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>
是一种老派的编码方式,在 JSP 版本 2 中,存在一种避免在 JSP 文件中使用 Java 代码的方法。什么是替代的 JSP 2 行,这种技术叫什么?
答:
JSTL 为条件、循环、集合、get 等提供标签。例如:
<c:if test="${someAttribute == 'something'}">
...
</c:if>
JSTL 使用请求属性 - 它们通常由 Servlet 在请求中设置,Servlet 转发到 JSP。
经验表明,JSP有一些缺点,其中之一是难以避免将标记与实际代码混合在一起。
如果可以,请考虑使用专门的技术来完成您需要做的事情。在 Java EE 6 中,有 JSF 2.0,它提供了许多不错的特性,包括通过该方法将 Java Bean 和 JSF 页面粘合在一起。#{bean.method(argument)}
评论
您可以将 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>
自从 2001 年标签库(如 JSTL)和 EL(表达式语言,这些东西)诞生以来,确实非常不鼓励在 JSP 中使用 scriptlet(这些东西)。<% %>
${}
scriptlet 的主要缺点是:
- 可重用性:不能重用 scriptlet。
- 可替换性:你不能使 scriptlet 抽象化。
- OO 能力:你不能使用继承/组合。
- 可调试性:如果 scriptlet 中途抛出异常,你得到的只是一个空白页。
- 可测试性:scriptlet 不可单元测试。
- 可维护性:每次 saldo 需要更多的时间来维护混合/杂乱/重复的代码逻辑。
太阳Oracle 本身也建议在 JSP 编码约定中,只要(标记)类可以实现相同的功能,就避免使用 scriptlet。以下是几个相关的引用:
从 JSP 1.2 规范开始,强烈建议在 Web 应用程序中使用 JSP 标准标记库 (JSTL),以帮助减少页面中对 JSP scriptlet 的需求。通常,使用 JSTL 的页面更易于阅读和维护。
...
在可能的情况下,每当标记库提供等效功能时,就避免使用 JSP scriptlet。这使得页面更易于阅读和维护,有助于将业务逻辑与表示逻辑分开,并使您的页面更容易演变为 JSP 2.0 样式的页面(JSP 2.0 规范支持但不强调使用 scriptlet)。
...
本着采用模型-视图-控制器 (MVC) 设计模式来减少表示层与业务逻辑之间的耦合的精神,不应使用 JSP scriptlet 来编写业务逻辑。相反,如果需要,可以使用 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. } }
当映射到覆盖感兴趣的 JSP 页面的适当位置时,您不需要复制粘贴整个 JSP 页面的同一段代码。
<url-pattern>
如果你想调用一些 Java 代码来处理 GET 请求,例如从数据库中预加载一些列表以显示在某个表中,如果需要,基于一些查询参数,那么在
doGet()
方法中实现一个 servlet 并相应地编写代码。例如: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 页面,无论如何,您都可以通过 in 自定义该页面。
<error-page>
web.xml
如果你想调用一些 Java 代码来处理 POST 请求,例如从提交的 HTML 表单中收集数据并用它做一些业务(转换、验证、保存在数据库中等),那么在
doPost()
方法中实现一个 servlet 并相应地编写代码。例如: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 的 Front Controller 模式实现 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 框架,如 JSF、Spring MVC、Wicket 等,这样您最终只需要一个 JSP/Facelets 页面和一个 JavaBean 类,而不需要自定义 servlet。
如果你想调用一些 Java 代码来控制 JSP 页面中的流,那么你需要获取一个(现有的)流控制标签库,比如 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样式的标签,可以很好地适应所有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 的一部分,已经无法使用 scriptlet。这样一来,你就会自动被迫以“正确的方式”做事。
如果要调用一些 Java 代码来访问和显示 JSP 页面中的“后端”数据,则需要使用 EL(表达式语言)之类的东西。例如,重新显示提交的输入值:
${}
<input type="text" name="foo" value="${param.foo}" />
显示 的结果。
${param.foo}
request.getParameter("foo")
如果要直接在 JSP 页面中调用某些实用程序 Java 代码(通常是方法),则需要将它们定义为 EL 函数。JSTL 中有一个标准的函数 taglib,但您也可以轻松地自己创建函数。下面是一个示例,说明如何使用 JSTL 来防止 XSS 攻击。
public static
fn:escapeXml
<%@ 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 漏洞。
另请参阅:
- JSP、Servlet 和 JSF 之间有什么区别?
- Servlet、ServletContext、HttpSession 和 HttpServletRequest/Response 如何工作?
- 使用 JSP、Servlet 和 JDBC 的基本 MVC 示例
- Java Web 应用程序中的设计模式
- JSP/Servlet 的隐藏功能
评论
<% response.getWriter().flush(); %>
</head>
<body>
在 MVC 体系结构模式中,JSP 表示视图层。在 JSP 中嵌入 Java 代码被认为是一种不好的做法。
您可以将 JSTL、freeMarker 和 velocity 与 JSP 一起使用作为“模板引擎”。
这些标记的数据提供程序取决于您正在处理的框架。Struts 2 和 WebWork 作为 MVC 模式的实现,使用了 OGNL“非常有趣的技术,将 Beans 属性暴露给 JSP”。
为了避免 JSP 文件中的 Java 代码,Java 现在提供了标记库,如 JSTL。
此外,Java 还提出了 JSF,您可以将所有编程结构以标签的形式写入其中。
还有一些基于组件的框架,例如 Wicket,可以为您生成大量 HTML。
最终出现在 HTML 中的标签非常基本,几乎没有任何逻辑可以混合其中。结果是几乎像空一样的 HTML 页面,具有典型的 HTML 元素。缺点是 Wicket API 中有很多组件需要学习,在这些约束下,有些事情可能很难实现。
Wicket 也是一种将 Java 与 HTML 完全分离的替代方案,因此设计师和程序员可以一起工作,并在不同的代码集上工作,而彼此之间几乎不了解。
看看检票口。
在 JSP 中使用 JSTL 标记库。这将完美地工作。
只需使用 JSTL 标记和 EL 表达式即可。
你提出了一个很好的问题,虽然你得到了很好的答案,但我建议你摆脱JSP。这是过时的技术,最终会消亡。使用现代方法,如模板引擎。您将非常清楚地分离业务层和表示层,并且模板中肯定没有 Java 代码,因此您可以直接从 Web 演示文稿编辑软件生成模板,在大多数情况下利用所见即所得。
当然要远离过滤器和前后处理,否则您可能会遇到支持/调试困难,因为您总是不知道变量从哪里获取值。
评论
作为保障措施:永久禁用 Scriptlet
正如另一个问题所讨论的那样,您可以并且始终应该在 Web 应用程序描述符中禁用 scriptlet。web.xml
我总是这样做,以防止任何开发人员添加脚本,尤其是在大公司中,您迟早会失去概览。设置如下所示:web.xml
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
评论
<% %>
<%! %>
<%= %>
<%@ %>
<%-- --%>
学习使用 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/ 中创建文件 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>
评论
如果我们在 Java Web 应用程序中使用以下内容,则可以从 JSP 文件的前台消除 Java 代码。
将 MVC 体系结构用于 Web 应用程序
使用 JSP 标记
a. 标准标签
b. 自定义标签
- 表达语言
如果你只是想避免 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 forwarding, 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>
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 命名空间中的一些特殊属性;它可以使用浏览器查看,并由设计师安全地进行调整。
还支持宏以及国际化和本地化:
<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 实现了解不多。
评论
ui:xxx
标记。
tal:replace="structure (expression)"
如果有人真的反对用多种语言编程,我建议使用 GWT。从理论上讲,您可以避免使用所有 JavaScript 和 HTML 元素,因为 Google 工具包会将所有客户端和共享代码转换为 JavaScript。你不会有问题,所以你有一个网络服务,没有用任何其他语言编码。你甚至可以在某个地方使用一些默认的CSS,因为它是由扩展(smartGWT或Vaadin)给出的。你不需要学习几十个注释。
当然,如果你愿意,你可以深入到代码的深处,注入 JavaScript 并丰富你的 HTML 页面,但如果你愿意,实际上你可以避免它,结果会很好,因为它是在任何其他框架中编写的。我说值得一试,而且基本的 GWT 是有据可查的。
当然,许多程序员在此描述或推荐了其他几种解决方案。GWT 适用于那些不想处理 Web 部件或将其最小化的人。
评论
无论你多么努力地避免,当你与其他开发人员合作时,他们中的一些人仍然会更喜欢 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>
在此主页上,我创建了一个名为“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)。此处标记内的所有内容都将替换母版页上的内容。您的子页面也可以包含任何标签库,您可以像提到的其他页面一样正常使用它。但是,如果您在此处使用任何 scriptlet 代码 (...) 并尝试运行此页面,您将得到一个 .因此,其他人无法将邪恶的代码包含在 jsp 文件中<jsp:body>
<jsp:doBody/>
<%= request.getParameter("name") %>
JasperException because Scripting elements ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <jsp:scriptlet ) are disallowed here
从控制器调用此页面:
您可以轻松地从控制器调用子 .jsp 文件。这也适用于支柱框架
评论
从技术上讲,JSP 在运行时都转换为 Servlet。
JSP 最初是为了按照 MVC 模式解耦业务逻辑和设计逻辑而创建的。因此,从技术上讲,JSP 是运行时的所有 Java 代码。
但为了回答这个问题,标记库通常用于将逻辑(删除 Java 代码)应用于 JSP 页面。
在 JSP 中使用 scriptlet 不是一个好的做法。
相反,您可以使用:
- JSTL 标签
- EL 表达式
- 自定义标签 - 您可以定义自己的标签来使用。
请参考:
当然,用事件生产者-消费者架构来代替,在这种架构中,业务层被告知需要增加计数器,它会做出相应的反应,并通知演示者,以便他们更新视图。这涉及到许多数据库事务,因为将来我们需要知道计数器的新旧值,谁增加了它以及出于什么目的。显然,这涉及到序列化,因为各层是完全解耦的。您将能够在 RMI、IIOP、SOAP 上增加计数器。但是只需要 HTML,您不需要实现,因为这是一个如此平凡的情况。您的新目标是在新的闪亮 E7、64GB RAM 服务器上达到每秒 250 次增量。<%! counter++; %>
我有 20 多年的编程经验,大多数项目在六重奏之前都失败了:可重用性 可替换性 OO 能力 可调试性 可测试性 甚至需要可维护性。其他项目由只关心功能的人运营,非常成功。此外,在项目中过早实现的僵硬对象结构使代码无法适应规范的剧烈变化(即敏捷)。
因此,我认为在项目早期或没有特别要求时定义“层”或冗余数据结构的活动是拖延。
如何避免 JSP 文件中的 Java 代码?
除了表达式语言 (EL) 之外,还可以使用 JSTL 等选项卡库标记。但是 EL 不能很好地与 JSP 配合使用。因此,最好完全放弃 JSP 并使用 Facelets。
Facelets 是第一个为 JSF(Java Server Faces)设计的非 JSP 页面声明语言,与 JSP 相比,它为 JSF 开发人员提供了更简单、更强大的编程模型。它解决了 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>
这些示例非常简单,但您可以在此处执行许多复杂的任务。请考虑您可以使用其他标签(例如:具有控制标签,如文本操作,甚至SQL标签),传递所有种类的参数,例如,access,,...在您的标签文件中也是如此。JSTL
if/forEcah/chosen
format/contains/uppercase
select/update
Hashmap
session
request
标签文件非常容易开发,因为在更改它们时不需要重新启动服务器,就像JSP文件一样。这使得它们易于开发。
即使你使用像 Struts 2 这样的框架,它有很多好的标签,你可能会发现拥有自己的标签可以大大减少你的代码。您可以将标签参数传递给 struts,这样可以自定义框架标签。
您不仅可以使用标签来避免使用 Java,还可以最小化 HTML 代码。一旦我看到我的页面中开始出现重复代码,我自己就会尝试查看 HTML 代码并构建大量标签。
(即使您最终在 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 一起使用即可。
还有其他选项,例如使用模板引擎,例如 Velocity、Freemarker、Thymeleaf 等。但是,大多数时候,将普通 JSP 与 EL 和 JSTL 一起使用可以满足我的目的,而且对于初学者来说似乎也是最简单的。
另外,请注意,在视图层中执行业务逻辑并不是最佳做法。您应该在服务层中执行业务逻辑, 并通过控制器将输出结果传递给视图。
我的朋友,这些东西都不再用了。我的建议是将视图(CSS、HTML、JavaScript 等)与服务器分离。
就我而言,我使用 Angular 处理视图的系统,并且使用 REST 服务从服务器获取所需的任何数据。
相信我,这将改变你的设计方式。
评论
使用Backbone.js或类似AngularJS的JavaScript框架进行UI设计 并使用 REST API 获取数据。这将从 UI 中完全删除 Java 依赖项。
- 在 servlet 类中设置值和参数
- 使用 JSTL/Taglib 在 JSP 中获取这些值和参数
这种方法的好处是你的代码也像 HTML 一样 法典!
这里的很多答案都是“使用框架”的路线。这没有错。但是,我不认为它真的回答了您的问题,因为框架可能会也可能不会使用 JSP,它们也不会以任何方式将删除 JSP 中的 java 使用作为主要目标。
对于“如何避免在 JSP 中使用 Java”这个问题,唯一好的答案是:你不能。
这就是 JSP 的用途 - 使用 Java 渲染具有动态数据/逻辑的 HTML。
接下来的问题可能是,我应该在我的 JSP 中使用多少 java。
在我们回答这个问题之前,您还应该思考,“我是否需要使用 JSP 来使用 Java 构建 Web 内容?最后一个问题的答案是否定的。除了 JSP 之外,还有许多替代方案可用于使用 Java 开发面向 Web 的应用程序。例如,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 个此类唯一代码段的实例。在类或标记库定义中进行这些更改是很有可能的,但由于每种情况的特殊性,它会非常复杂,需要更长的时间来编写和调试,因此需要更多的时间才能到达我的用户。这是一个判断电话。但不要误会,你不能用“没有 java”来编写任何意义的 JSP,你也不想这样做。这种能力的存在是有原因的。
评论
Java 本身是一门非常好的语言,但在企业环境中的大量使用使其标准解决方案变得极其(荒谬)困难。示例:JSTL、JSF、Wicket 等。
这是在 Java 中创建后端的超轻量级方法:
- 根本不使用 JSP(或任何其他模板引擎);
- 使用纯 HTML 模板;
- 使用 JSOUP 将 HTML 模板解析为 Document 对象;
- 使用其非常直观的类似jQuery的方法修改Document对象;
- 返回 Document.toString() 作为对请求的响应。
我将它用于我的一个副项目(托管 Digitalocean $5 droplet、Nginx、Tomcat),它非常快:根据 Googlebot 的数据,平均响应时间约为 160 毫秒。
评论