JSP/Servlet的隐藏功能 [英] Hidden features of JSP/Servlet

查看:78
本文介绍了JSP/Servlet的隐藏功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对编写JSP/Servlet时使用的技巧很感兴趣.我将开始:

I am interested in your tricks etc used when writing JSP/Servlet. I will start:

我最近发现了如何将一个JSP标记的输出包含在另一个标记的属性中的方法:

I somewhat recently found out how you can include the output of one JSP tag in an attribute of another tag:

<c:forEach items="${items}">
  <jsp:attribute name="var">
    <mytag:doesSomething/>
  </jsp:attribute>
  <jsp:body>
    <%-- when using jsp:attribute the body must be in this tag --%>
  </jsp:body>
</c:forEach>

推荐答案

注意:我发现很难想到任何隐藏功能".用于JSP/Servlet.我认为,最佳做法"是一个更好的措词,我可以想到其中的任何一个.这实际上还取决于您对JSP/Servlet的经验.经过多年的开发,您看不到那些隐藏的功能"不再.无论如何,我都会列出其中一些最佳做法",我多年以来发现其中的许多入门者并没有完全意识到这一点.这些将被归类为隐藏特征".在许多初学者眼中.无论如何,这是列表:)

通过将JSP文件放置在/WEB-INF文件夹中,可以有效地将它们隐藏起来,例如通过http://example.com/contextname/WEB-INF/page.jsp直接访问它们.这将导致404.然后,您只能通过 RequestDispatcher 访问它们在Servlet中或使用 jsp:include .

By placing JSP files in /WEB-INF folder you effectively hide them from direct access by for example http://example.com/contextname/WEB-INF/page.jsp. This will result in a 404. You can then only access them by a RequestDispatcher in Servlet or using jsp:include.

大多数人都了解Servlet的 doGet() 方法来处理JSP请求.例如:

Most are aware about Servlet's doPost() to post-process a request (a form submit), but most don't know that you can use Servlet's doGet() method to pre-process a request for a JSP. For example:

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的帮助下显示:

which is used to preload some tabular data which is to be displayed with help of JSTL's c:forEach:

<table>
    <c:forEach items="${items}" var="item">
        <tr><td>${item.id}</td><td>${item.name}</td></tr>
    </c:forEach>
</table>

将这样的servlet映射到/page(或/page/*)的url-pattern上,只需通过浏览器地址栏或简单的香草链接调用http://example.com/contextname/page即可运行它.另请参见 Servlet中的doGet和doPost .

Map such a servlet on an url-pattern of /page (or /page/*) and just invoke http://example.com/contextname/page by browser address bar or a plain vanilla link to run it. See also e.g. doGet and doPost in Servlets.

您可以在 jsp:include 中使用EL:

You can use EL in jsp:include:

<jsp:include page="/WEB-INF/${bean.page}.jsp" />

bean.getPage()只能返回有效的页面名称.

The bean.getPage() can just return a valid pagename.

EL本身并不要求要访问的对象是完全有价值的 Javabean.前缀为getis的noarg方法的存在足以在EL中访问它.例如:

EL does not per-se require the object-to-be-accessed to be a fullworthy Javabean. The presence of a no-arg method which is prefixed with get or is is more than sufficient to access it in EL. E.g.:

${bean['class'].name}

这将返回 bean.getClass().getName() ,其中getClass()方法实际上是从[]由于此处提到的原因 EL表示语言中的检查实例.

This returns the value of bean.getClass().getName() where the getClass() method is actually inherited from Object#getClass(). Note that class is specified using "brace notation" [] for reasons mentioned here instanceof check in EL expression language.

${pageContext.session.id}

这将返回 pageContext.getSession().getId() 在ao中很有用小程序可以与Servlet实例进行通信.

${pageContext.request.contextPath}

这将返回 pageContext.getRequest().getContextPath() 在ao中很有用如何使用相对路径而不包含上下文根名字?

以下EL符号

${bean.map.foo}

解析为bean.getMap().get("foo").如果Map键包含一个点,则可以使用大括号符号"来表示. [],带引号的键:

resolves to bean.getMap().get("foo"). If the Map key contains a dot, you can use the "brace notation" [] with a quoted key:

${bean.map['foo.bar']}

解析为bean.getMap().get("foo.bar").如果要使用动态键,请同时使用大括号符号,但不要用引号将其括起来:

which resolves to bean.getMap().get("foo.bar"). If you want a dynamic key, use brace notation as well, but then unquoted:

${bean.map[otherbean.key]}

解析为bean.getMap().get(otherbean.getKey()).

您可以使用 c:forEach Map上进行迭代.每次迭代都会给出 Map.Entry 依次具有getKey()getValue()方法(以便您可以通过${entry.key}${entry.value}在EL中访问它).示例:

You can use c:forEach as well to iterate over a Map. Each iteration gives a Map.Entry which in turn has getKey() and getValue() methods (so that you can just access it in EL by ${entry.key} and ${entry.value}). Example:

<c:forEach items="${bean.map}" var="entry">
    Key: ${entry.key}, Value: ${entry.value} <br>
</c:forEach>

另请参见使用jstl进行调试-具体如何?

您可以使用 jsp:useBean 和格式来获取当前日期借助JSTL fmt:formatDate

You can get the current's date with jsp:useBean and format it with help of JSTL fmt:formatDate

<jsp:useBean id="date" class="java.util.Date" />
...
<p>Copyright &copy; <fmt:formatDate value="${date}" pattern="yyyy" /></p>

(目前)打印如下:"Copyright©2010".

This prints (as of now) like follows: "Copyright © 2010".

拥有友好URL的一种简单方法是利用

An easy way to have friendly URL's is to make use of HttpServletRequest#getPathInfo() and JSP's hidden in /WEB-INF:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/WEB-INF" + request.getPathInfo() + ".jsp").forward(request, response);
}

如果将此servlet映射到例如/pages/*,则在http://example.com/contextname/pages/foo/bar上的请求将有效显示/WEB-INF/foo/bar.jsp.您可以通过拆分/上的pathinfo进一步走一步,仅将第一部分作为JSP页面URL,将剩余部分作为业务操作". (让Servlet充当页面控制器).另请参见设计模式"基于Web的应用程序.

If you map this servlet on for example /pages/*, then a request on http://example.com/contextname/pages/foo/bar will effectively display /WEB-INF/foo/bar.jsp. You can get a step further by splitting the pathinfo on / and only take the first part as JSP page URL and the remnant as "business actions" (let the servlet act as a page controller). See also e.g. Design Patterns web based applications.

隐式EL对象${param},它引用

The implicit EL object ${param} which refers to the HttpServletRequest#getParameterMap() can be used to redisplay user input after a form submit in JSP:

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

这基本上与request.getParameterMap().get("foo")相同.另请参见如何提交表单到Servlet之后,我在JSP中保留HTML表单字段值吗?
别忘了阻止XSS!参见下一章.

This basically does the same as request.getParameterMap().get("foo"). See also e.g. How can I retain HTML form field values in JSP after submitting form to Servlet?
Don't forget to prevent from XSS! See following chapter.

要防止您的网站 XSS ,您要做的就是(re )使用JSTL 用户控制数据" rel ="noreferrer"> fn:escapeXml

To prevent your site from XSS, all you need to do is to (re)display user-controlled data using JSTL fn:escapeXml or c:out.

<p><input type="text" name="foo" value="${fn:escapeXml(param.foo)}">
<p><c:out value="${bean.userdata}" />


LoopTagStatus替换<table>

JSTL的varStatus属性 c:forEach 为您提供了 LoopTagStatus 后面有几种吸气方法(可以在EL中使用!).因此,要检查偶数行,只需检查loop.getIndex() % 2 == 0:


Alternating <table> rows with LoopTagStatus

The varStatus attribute of JSTL c:forEach gives you a LoopTagStatus back which in turn has several getter methods (which can be used in EL!). So, to check for even rows, just check if loop.getIndex() % 2 == 0:

<table>
    <c:forEach items="${items}" var="item" varStatus="loop">
        <tr class="${loop.index % 2 == 0 ? 'even' : 'odd'}">...</tr>
    <c:forEach>
</table>

将有效地以

<table>
    <tr class="even">...</tr>
    <tr class="odd">...</tr>
    <tr class="even">...</tr>
    <tr class="odd">...</tr>
    ...
</table>

使用CSS为他们提供不同的背景颜色.

Use CSS to give them a different background color.

tr.even { background: #eee; }
tr.odd { background: #ddd; }


使用LoopTagStatus从列表/数组中填充逗号分隔的字符串:

另一个有用的 LoopTagStatus 方法是 isLast() :


Populate commasepared string from List/Array with LoopTagStatus:

Another useful LoopTagStatus method is the isLast():

<c:forEach items="${items}" var="item" varStatus="loop">
    ${item}${!loop.last ? ', ' : ''}
<c:forEach>

其结果类似于item1, item2, item3.

您可以将public static实用程序方法声明为EL函数(例如

You can declare public static utility methods as EL functions (like as JSTL functions) so that you can use them in EL. E.g.

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

如下所示:

with /WEB-INF/functions.tld which look like follows:

<?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>


获取原始请求网址和查询字符串

如果已转发JSP,则可以通过以下方式获取原始请求URL,


Get the original request URL and query string

If the JSP has been forwarded, you can get the original request URL by,

${requestScope['javax.servlet.forward.request_uri']} 

和原始请求查询字符串,

and the original request query string by,

${requestScope['javax.servlet.forward.query_string']}


到目前为止.也许我迟早会添加一些.

这篇关于JSP/Servlet的隐藏功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆