<!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>
How to replace scriptlets entirely depends on the sole purpose of the code/logic. More than often this code is to be placed in a fullworthy Java class:
如果要在每个请求上调用 same Java代码,不管请求的页面是什么,都要少或多,例如检查用户是否已登录,然后在doFilter()方法中实现filter并相应地编写代码 . 例如 . :
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.
}
}
使用XML样式的标签非常适合所有HTML,代码比一堆各种各样的Scriptlet更易读(因此更易于维护)打开和关闭括号("Where the heck does this closing brace belong to?") . 一个简单的帮助是配置您的Web应用程序,以便在使用scriptlet时通过将以下部分添加到 web.xml 来抛出异常:
请注意,XSS灵敏度绝不与Java / JSP / JSTL / EL /无关,在您开发的 every Web应用程序中需要考虑此问题 . scriptlet的问题在于它无法提供内置预防,至少不使用标准Java API . JSP 's successor Facelets has already implicit HTML escaping, so you don'需要担心Facelets中的XSS漏洞 .
如果可以,那么请考虑使用专门的技术来完成您的工作 . 在Java EE 6中有JSF 2.0,它提供了许多不错的功能,包括通过 #{bean.method(argument)} 方法将Java bean与JSF页面粘合在一起 .
12
If somebody is really against programming in more languages than one ,我建议GWT,理论上你可以避免所有的JS和HTML元素,因为Google Toolkit将所有的客户端和共享代码转换为JS,你赢了't have problem with them, so you have a webservice without coding in any other languages. Even you can use some default CSS from somewhere as it is given by extensions (smartGWT or Vaadin). You don' t需要学习几十个注释 .
Technically, JSP are all converted to Servlets during runtime . JSP最初是为了按照MVC模式解耦业务逻辑和设计逻辑而创建的 . 所以JSP在运行时在技术上都是java代码 . 但回答这个问题,Tag Libraries通常用于将逻辑(删除Java代码)应用于JSP页面 .
30 回答
只需使用JSTL标记和EL表达式 .
如果我们在java Web应用程序中使用以下内容,则可以从JSP的前台删除Java代码 .
将MVC架构用于Web应用程序
使用JSP标记
一个 . 标准标签
湾自定义标签
为了避免JSP文件中的java代码,java现在提供了像JSTL这样的标记库,java也提出了JSF,你可以用标签的形式编写所有的编程结构
无论你多么努力避免,当你与其他开发人员合作时,他们中的一些人仍然会喜欢scriptlet,然后将邪恶的代码插入到项目中 . 因此,如果您真的想减少scriptlet代码,那么在第一个符号设置项目非常重要 . 有几种技术可以克服这个问题(包括其他提到的几个框架) . 但是,如果您更喜欢纯JSP方式,那么请使用JSTL标记文件 . 关于这一点的好处是您还可以为项目设置母版页,因此其他页面可以继承母版页
Create a master page called base.tag under your WEB-INF/tags with the following content
<%@ 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/>
将替换为子页面的内容Create child page (child.jsp) in your WebContent folder:
<T:碱>
<jsp:attribute name =“title”>
<bean:message key =“hello.world”/>
</ JSP:属性>
<JSP:主体>
[把你孩子的内容放在这里]
</ JSP:主体>
</吨:碱>
<t:base>
用于指定要使用的母版页(此时为base.tag) . 标签<jsp:body>
中的所有内容都将替换主页面上的<jsp:doBody/>
. 您的子页面还可以包含任何标记库,您可以像通常提到的那样使用它 . 但是,如果您在此处使用任何scriptlet代码(<%= request.getParameter("name") %>
...)并尝试运行此页面,您将获得JasperException because Scripting elements ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <jsp:scriptlet ) are disallowed here
. 因此,其他人无法将邪恶代码包含在jsp文件中Calling this page from your controller:
您可以从控制器轻松调用child.jsp文件 . 这对struts框架也很好用
通过将JSTL标记与EL表达式一起使用,您可以避免这种情况 . 在jsp页面中添加以下内容:
在JSP中使用scriptlet不是一个好习惯 .
相反,您可以使用:
JSTL标签
EL表达式
自定义标签 - 您可以定义自己的标签 .
请参阅:
http://docs.oracle.com/javaee/1.4/tutorial/doc/JSTL3.html
EL
在servlet类中创建值和参数
使用JSTL / Taglib获取JSP中的这些值和参数
在MVC架构模式中,JSP表示View层 . 在JSP中嵌入Java代码被认为是一种不好的做法 . 您可以将JSTL,freeMarker,velocity与JSP一起用作"template engine" . 您正在处理的那些标签 depends on frameworks 的数据提供者 .
Struts 2
和webwork
作为MVC模式的实现使用OGNL "very interesting technique to expose Beans Properties to JSP " .JSP 2.0有一个名为 "Tag Files" 的功能,你可以编写没有外部
java
代码和tld
的标签 . 您需要创建一个.tag
文件并将其放在WEB-INF\tags
中,您甚至可以创建一个目录结构来打包您的标签 .例如:
用它就好
此外,您可以轻松阅读标签正文
用它
样本非常简单,但您可以在这里完成许多复杂的任务 . 请考虑您可以使用其他标签(例如:
JSTL
,其中包含控制标签,如if/forEcah/chosen
文本操作,如format/contains/uppercase
甚至SQL标签select/update
),传递所有类型的参数,例如Hashmap
,访问session
,request
,...也在您的标签文件中 .Tag File 非常容易开发,因为您在更改服务器时不需要重新启动服务器,例如JSP文件 . 这使它们易于开发 .
即使你使用像Struts 2这样的框架,它有很多好的标签,你可能会发现拥有自己的标签可以减少你的代码 . 您可以将标记参数传递给struts,这样就可以自定义框架标记 .
您不仅可以使用标记来避免使用Java,还可以最小化HTML代码 . 我自己尝试查看HTML代码并在看到代码后立即构建标签重复从我的页面开始 .
(即使您最终在JSP代码中使用java,我希望不会,您可以将该代码封装在标记中)
Learn to customize and write your own tags using JSTL
请注意,EL是 EviL (运行时异常,重构)
Wicket也可能是邪恶的(性能,对于小应用程序或简单的视图层来说很难)
来自java2s的示例,
这必须添加到Web应用程序的web.xml中
在/ WEB-INF /中创建文件:java2s.tld
将以下代码编译为WEB-INF \ classes \ com \ java2s
启动服务器并在浏览器中加载bodyContent.jsp
正如许多答案所说,使用JSTL或创建自己的自定义标签 . Here是关于创建自定义标签的很好的解释
自从2001年诞生taglibs(如JSTL)和EL(Expression Language,那些
${}
事物)以来,JSP中对scriptlet(那些<% %>
事物)的使用确实非常气馁 .scriptlet的主要缺点是:
Reusability: 您无法重用scriptlet .
Replaceability: 你不能使scriptlet抽象化 .
OO-ability: 你无法利用继承/组合 .
Debuggability: 如果scriptlet中途抛出异常,你得到的只是一个空白页面 .
Testability: scriptlet不是可单元测试的 .
每个saldo需要更多时间来维持混杂/混乱/重复的代码逻辑 .
Sun Oracle本身也建议在JSP coding conventions中避免在(标记)类可能的情况下使用scriptlet . 以下是几个相关的引用:
How to replace scriptlets entirely depends on the sole purpose of the code/logic. More than often this code is to be placed in a fullworthy Java class:
当映射到适当的
<url-pattern>
覆盖感兴趣的JSP页面时,那么您不需要在整个JSP页面中复制相同的代码片段 .这种处理异常的方式更容易 . 在JSP渲染过程中不会访问DB,但是在JSP显示之前 . 每当数据库访问引发异常时,您仍然可以更改响应 . 在上面的示例中,将显示默认错误500页面,您可以通过
web.xml
中的<error-page>
进行自定义 .这样处理不同的结果页面目标更容易:在出现错误时重新显示带有验证错误的表单(在此特定示例中,您可以使用EL中的
${message}
重新显示它),或者只是在成功的情况下转到所需的目标页面 .或者只是采用像JSF,Spring MVC,Wicket等MVC框架,这样你最终只需要一个JSP / Facelets页面和一个JavaBean类,而不需要自定义的servlet .
List<Product>
:使用XML样式的标签非常适合所有HTML,代码比一堆各种各样的Scriptlet更易读(因此更易于维护)打开和关闭括号("Where the heck does this closing brace belong to?") . 一个简单的帮助是配置您的Web应用程序,以便在使用scriptlet时通过将以下部分添加到
web.xml
来抛出异常:在Facelets中,JSP的后继者是Java EE提供的MVC框架JSF的一部分,它已经 not 可以使用scriptlet . 这样你自动被迫做事"the right way" .
${}
事物 . 例如 . 重新显示提交的输入值:${param.foo}
显示request.getParameter("foo")
的结果 .public static
方法),则需要将它们定义为EL函数 . 在JSTL中有一个标准的functions taglib,但是you can also easily create functions yourself . 以下是JSTLfn:escapeXml
如何用于防止XSS attacks的示例 .请注意,XSS灵敏度绝不与Java / JSP / JSTL / EL /无关,在您开发的 every Web应用程序中需要考虑此问题 . scriptlet的问题在于它无法提供内置预防,至少不使用标准Java API . JSP 's successor Facelets has already implicit HTML escaping, so you don'需要担心Facelets中的XSS漏洞 .
另见:
What's the difference between JSP, Servlet and JSF?
How does Servlet, ServletContext, HttpSession and HttpServletRequest/Response work?
Basic MVC example with JSP, Servlet and JDBC
Design patterns in Java web applications
Hidden features of JSP/Servlet
您可以将JSTL标记与EL表达式一起使用,以避免混合使用Java和HTML代码:
JSTL为条件,循环,集合,获取等提供标签 . 例如:
JSTL使用请求属性 - 它们通常由Servlet设置在请求中,Servlet转发到JSP .
As a Safeguard: Disable Scriptlets For Good
正如another question所讨论的那样,您可以并且始终应该在
web.xml
Web应用程序描述符中禁用scriptlet .我总是这样做是为了防止任何开发人员添加scriptlet,特别是在大型公司中,您迟早会丢失概述 .
web.xml
设置如下所示:还有一些基于组件的框架,如 Wicket ,可以为您生成大量的HTML . 最终在HTML中的标签非常基本,几乎没有混合的逻辑 . 结果几乎是空的HTML页面,具有典型的HTML元素 . 缺点是 Wicket API中有很多组件要学习,有些事情在这些限制条件下很难实现 .
在JSP中使用 JSTL Tag libraries ,这将是完美的 .
经验表明,JSP有一些缺点,其中一个难以避免将标记与实际代码混合 .
如果可以,那么请考虑使用专门的技术来完成您的工作 . 在Java EE 6中有JSF 2.0,它提供了许多不错的功能,包括通过
#{bean.method(argument)}
方法将Java bean与JSF页面粘合在一起 .If somebody is really against programming in more languages than one ,我建议GWT,理论上你可以避免所有的JS和HTML元素,因为Google Toolkit将所有的客户端和共享代码转换为JS,你赢了't have problem with them, so you have a webservice without coding in any other languages. Even you can use some default CSS from somewhere as it is given by extensions (smartGWT or Vaadin). You don' t需要学习几十个注释 .
当然,如果你愿意,你可以深入了解代码的深度并注入JS并丰富你的HTML页面,但是如果你愿意的话,你真的可以避免它,结果会很好,因为它是在任何其他框架中编写的 . 我说值得一试,基本的GWT已经有了很好的记录 .
当然,许多其他程序员在此描述或推荐了其他几种解决方案 . GWT适用于那些真正不想处理Web部件或将其最小化的人 .
来自Python世界的一个巧妙的想法是模板属性语言; TAL是由Zope引入的(因此是a.k.a. "Zope Page Templates",ZPT)并且是标准的,在PHP,XSLT和Java中也有实现(我使用了Python / Zope和PHP的化身) . 在这类模板语言中,上面的一个示例可能如下所示:
代码看起来像普通的HTML(或XHTML)以及XML命名空间中的一些特殊属性;它可以通过浏览器查看,并由设计师安全地进行调整 . 支持宏和i18n:
如果内容的翻译可用,则使用它们 .
不过,我对Java implementation不太了解 .
使用骨干,角度类似javascript框架进行UI设计,并使用rest api获取数据 . 这将完全从UI中删除java依赖项 .
Wicket也是一种完全将java与html分开的替代方案,因此设计人员和程序员可以在不同的代码集上协同工作,彼此之间几乎没有相互理解 .
看看Wicket .
我不确定我是否正确 .
你应该阅读一些关于MVC的内容 . Spring MVC&Struts 2是两种最常见的解决方案 .
你提出了一个很好的问题你得到了很好的答案,我建议你摆脱JSP . 它是过时的技术,最终将死亡 . 使用现代方法,如模板引擎 . 您将非常清楚地分离业务层和表示层,当然模板中没有Java代码,因此您可以直接从Web演示文稿编辑软件生成模板,在大多数情况下可以利用WYSIWYG .
当然要远离过滤器以及前后处理,否则你可能会遇到支持/调试困难,因为你总是不知道变量获取值的位置 .
Technically, JSP are all converted to Servlets during runtime . JSP最初是为了按照MVC模式解耦业务逻辑和设计逻辑而创建的 . 所以JSP在运行时在技术上都是java代码 . 但回答这个问题,Tag Libraries通常用于将逻辑(删除Java代码)应用于JSP页面 .
如果您只是想避免JSP中Java编码的缺点,即使使用scriplet也可以这样做 . 只需按照一些规则在JSP中使用最少的Java,在JSP页面中几乎不需要计算和逻辑 .
当然,由事件 生产环境 者 - 消费者体系结构替换
<%! counter++; %>
,其中业务层被通知需要递增计数器,它会作出相应的反应,并通知演示者以便他们更新视图 . 涉及许多数据库事务,因为将来我们需要知道计数器的新旧值,谁已经增加了它并且考虑了什么目的 . 显然涉及序列化,因为这些层完全是分离的 . 您将能够通过RMI,IIOP,SOAP递增计数器 . 但是只需要HTML,这是你没有实现的,因为它是如此平凡的情况 . 您的新目标是在新的闪亮E7,64GB RAM服务器上每秒达到250个增量 .我有超过20年的编程经验,大多数项目在六重奏之前都失败了:可重用性可替换性OO能力可调试性可测性甚至还需要可维护性 . 由仅关注功能的人经营的其他项目非常成功 . 此外,在项目中过早实施的僵硬对象结构使得代码无法适应规范中的剧烈变化(也称为敏捷) .
所以我认为拖延是在项目早期或没有特别要求时定义“层”或冗余数据结构的活动 .
How to avoid Java code in JSP files?
除了表达式语言( EL )之外,您还可以使用 JSTL 之类的制表符库标记 . 但EL与JSP不兼容 . 所以最好完全删除JSP并使用 Facelets .
Facelets 是第一个为 JSF (Java Server Faces) 设计的非JSP页面声明语言,与JSP相比,它为JSF开发人员提供了一种更简单,更强大的编程模型 . 它解决了JSP中用于Web应用程序开发的不同问题 .
使用Scriptlet是一种非常古老的方式,不推荐使用 . 如果要在JSP页面中直接输出内容,只需使用 Expression Language(EL) 和 JSTL .
还有其他选项,比如使用模板引擎,如Velocity,Freemarker,Thymeleaf等 . 但是使用带有EL和JSTL的普通JSP大部分时间都是我的目的,对初学者来说似乎也是最简单的 .
另外,请注意,在视图层中执行业务逻辑不是最佳实践,您应该在服务层中执行业务逻辑,并通过Controller将输出结果传递给视图 .
我的朋友不再使用它,我的建议是从服务器中分离视图(css,html,javascript等) .
在我的情况下,我使用Angular处理视图,并使用rest服务从服务器获取所需的任何数据 .
相信我,这将改变你的设计方式