注意:我发现很难想到JSP / Servlet的任何“隐藏功能”。我认为“最佳做法”是一个更好的措辞,我可以想到其中的任何一种。这实际上还取决于您对JSP
/
Servlet的经验。经过多年的发展,您不再看到那些“隐藏的功能”。无论如何,我将列出一些小小的“最佳实践”,这些年来,我发现许多入门者并未完全意识到这一点。在许多入门者看来,这些将被归类为“隐藏功能”。无论如何,这是列表:)
隐藏JSP页面以免直接访问
通过将JSP文件放置在
/WEB-INF文件夹中,您可以有效地隐藏它们,例如,防止直接访问它们
http://example.com/contextname/WEB-INF/page.jsp。这将导致
404。然后,您只能通过
RequestDispatcherServlet中的或使用来访问它们
jsp:include。
预处理JSP请求
大多数人都知道Servlet
doPost()可以对请求(表单提交)进行 后
处理,但是大多数人不知道可以使用Servlet的
doGet()方法对JSP的请求进行 预处理 。例如:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Item> items = itemDAO.list(); request.setAttribute("items", items); request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);}用于预加载一些表格数据,这些数据将在JSTL的帮助下显示
c:forEach:
<table> <c:forEach items="${items}" var="item"> <tr><td>${item.id}</td><td>${item.name}</td></tr> </c:forEach></table>将这样的servlet映射
url-pattern到
/page(或
/page/*)上,然后仅
http://example.com/contextname/page通过浏览器地址栏或简单的普通链接调用即可运行它。
动态包含
您可以在
jsp:include以下位置使用EL
:
<jsp:include page="/WEB-INF/${bean.page}.jsp" />该
bean.getPage()可以只返回一个有效的页面名称。
EL可以访问任何吸气剂
EL本身并不要求要访问的对象是 完整的 Javabean。存在以no为前缀的noarg方法
get或
is足以在EL中访问它的方法。例如:
${bean['class'].name}这将返回方法实际继承自的
bean.getClass().getName()位置的值。请注意,出于此处提到的原因,使用“大括号表示法”指定了EL表达式语言中的instanceof
check。
getClass()
Object#getClass()
class``[]
${pageContext.session.id}这返回的值
pageContext.getSession().getId()在小程序可以与servlet实例通信时有用。
${pageContext.request.contextPath}这将返回
pageContext.getRequest().getContextPath()在ao中有用的值。如何在不包含上下文根名称的情况下使用相对路径?
EL也可以访问地图
以下EL表示法
${bean.map.foo}决定解决
bean.getMap().get("foo")。如果Map键包含点,则可以在
[]带引号的键中使用“括号符号” :
${bean.map['foo.bar']}解决为
bean.getMap().get("foo.bar")。如果要使用动态键,请同时使用大括号符号,但不要使用引号:${bean.map[otherbean.key]}解决为
bean.getMap().get(otherbean.getKey())。
使用JSTL遍历Map
您也可以使用
c:forEach来迭代
Map。每次迭代都给出一个
Map.Entry具有
getKey()和
getValue()方法的,这样您就可以通过
${entry.key}和在EL中对其进行访问${entry.value}。例:<c:forEach items="${bean.map}" var="entry"> Key: ${entry.key}, Value: ${entry.value} <br></c:forEach>另请参见例如使用jstl进行调试-
究竟如何?
在JSP中获取当前日期
您可以
jsp:useBean使用JSTL
获取当前日期并进行格式化
fmt:formatDate
<jsp:useBean id="date" />...<p>Copyright © <fmt:formatDate value="${date}" pattern="yyyy" /></p>如下所示(到目前为止)打印:“版权所有©2010”。
简单友好的URL
具有友好URL的一种简单方法是利用
HttpServletRequest#getPathInfo()和JSP隐藏在中
/WEB-INF:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF" + request.getPathInfo() + ".jsp").forward(request, response);}例如
/pages/*,如果将此servlet映射到,
http://example.com/contextname/pages/foo/bar则将有效显示一个请求
/WEB-INF/foo/bar.jsp。您可以通过分割pathinfo来进一步
/,仅将第一部分作为JSP页面URL,将其余部分作为“业务操作”(让Servlet充当
页面控制器
)。另请参见例如基于设计模式Web的应用程序。
使用以下命令重新显示用户输入 ${param}
在JSP中提交表单后
${param},引用的隐式EL对象HttpServletRequest#getParameterMap()可用于重新显示用户输入:
<input type="text" name="foo" value="${param.foo}">这基本上与相同
request.getParameterMap().get("foo")。另请参见例如,在将表单提交给Servlet之后如何在JSP中保留HTML表单字段值?不要忘记阻止XSS!请参阅下一章。
JSTL防止XSS
为了防止您的网站受到XSS的攻击,您需要做的就是使用JSTL 或重新显示 用户控制的
数据。
fn:escapeXml
c:out
<p><input type="text" name="foo" value="${fn:escapeXml(param.foo)}"><p><c:out value="${bean.userdata}" /><table>
与交替行LoopTagStatus
varStatusJSTL
的属性
c:forEach为您提供了一个
LoopTagStatus背景,该背景又具有几个getter方法(可以在EL!中使用)。因此,要检查偶数行,只需检查
loop.getIndex()% 2 == 0:
<table> <c:forEach items="${items}" var="item" varStatus="loop"> <tr >...</tr> <c:forEach></table>这将有效地结束于
<table> <tr >...</tr> <tr >...</tr> <tr >...</tr> <tr >...</tr> ...</table>
使用CSS为他们提供不同的背景颜色。
tr.even { background: #eee; }tr.odd { background: #ddd; }使用以下命令填充列表/数组中的逗号分隔的字符串LoopTagStatus
:
另一个有用的
LoopTagStatus方法是
isLast():
<c:forEach items="${items}" var="item" varStatus="loop"> ${item}${!loop.last ? ', ' : ''}<c:forEach>结果就是这样
item1, item2, item3。
EL功能
您可以将
publicstatic实用程序方法声明为EL函数(例如JSTL函数),以便可以在EL中使用它们。例如
package com.example;public final class Functions { private Functions() {} public static boolean matches(String string, String pattern) { return string.matches(pattern); }}用
/WEB-INF/functions.tld看起来像如下:
<?xml version="1.0" encoding="UTF-8" ?><taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>Custom_Functions</short-name> <uri>http://example.com/functions</uri> <function> <name>matches</name> <function-class>com.example.Functions</function-class> <function-signature>boolean matches(java.lang.String, java.lang.String)</function-signature> </function></taglib>
可以用作
<%@taglib uri="http://example.com/functions" prefix="f" %><c:if test="${f:matches(bean.value, '^foo.*')}"> ...</c:if>获取原始请求URL和查询字符串
如果已转发JSP,则可以通过以下方式获取原始请求URL:
${requestScope['javax.servlet.forward.request_uri']}和原始请求查询字符串,
${requestScope['javax.servlet.forward.query_string']}到目前为止。也许我迟早会添加一些。



