The use of scriptlets (those <% %>
things) in JSP is indeed highly discouraged since the birth of taglibs (like JSTL ) and EL ( Expression Language , those ${}
things) way back in 2001.
(自从2001年诞生taglibs (如JSTL )和EL ( 表达语言 ,那些${}
事物)以来,在JSP中使用scriptlet (那些<% %>
事物)的确非常不鼓励。)
The major disadvantages of scriptlets are:
(scriptlet的主要缺点是:)
- Reusability: you can't reuse scriptlets.
(可重用性:您无法重用scriptlet。)
- Replaceability: you can't make scriptlets abstract.
(可替换性:您不能使scriptlet抽象化。)
- OO-ability: you can't make use of inheritance/composition.
(OO-ability:你不能利用继承/组合。)
- Debuggability: if scriptlet throws an exception halfway, all you get is a blank page.
(可调试性:如果scriptlet中途抛出异常,你得到的只是一个空白页面。)
- Testability: scriptlets are not unit-testable.
(可测试性: scriptlet不是可单元测试的。)
- Maintainability: per saldo more time is needed to maintain mingled/cluttered/duplicated code logic.
(可维护性:每个saldo需要更多时间来维护混杂/混乱/重复的代码逻辑。)
Sun
Oracle itself also recommends in the JSP coding conventions to avoid use of scriptlets whenever the same functionality is possible by (tag) classes.
(
Sun
Oracle本身也建议在JSP编码约定中避免在(标记)类可能的情况下使用scriptlet 。)
Here are several cites of relevance: (以下是几个相关的引用:)
From JSP 1.2 Specification, it is highly recommended that the JSP Standard Tag Library (JSTL) be used in your web application to help reduce the need for JSP scriptlets in your pages.
(从JSP 1.2规范中,强烈建议在Web应用程序中使用JSP标准标记库(JSTL),以帮助减少页面中对JSP scriptlet的需求 。)
Pages that use JSTL are, in general, easier to read and maintain. (通常,使用JSTL的页面更易于阅读和维护。)
...
(...)
Where possible, avoid JSP scriptlets whenever tag libraries provide equivalent functionality.
(尽可能在标记库提供等效功能时避免使用JSP scriptlet 。)
This makes pages easier to read and maintain, helps to separate business logic from presentation logic, and will make your pages easier to evolve into JSP 2.0-style pages (JSP 2.0 Specification supports but de-emphasizes the use of scriptlets). (这使得页面更易于阅读和维护,有助于将业务逻辑与表示逻辑分离,并使您的页面更容易演变为JSP 2.0样式的页面(JSP 2.0规范支持但不强调使用scriptlet)。)
...
(...)
In the spirit of adopting the model-view-controller (MVC) design pattern to reduce coupling between the presentation tier from the business logic, JSP scriptlets should not be used for writing business logic.
(本着采用模型 - 视图 - 控制器(MVC)设计模式以减少表示层与业务逻辑之间的耦合的精神, JSP scriptlet不应用于编写业务逻辑。)
Rather, JSP scriptlets are used if necessary to transform data (also called "value objects") returned from processing the client's requests into a proper client-ready format. (相反,如果需要,可以使用JSP scriptlet将从处理客户端请求返回的数据(也称为“值对象”)转换为适当的客户端就绪格式。)
Even then, this would be better done with a front controller servlet or a custom tag. (即使这样,使用前端控制器servlet或自定义标签也可以做得更好。)
How to replace scriptlets entirely depends on the sole purpose of the code/logic.
(如何完全替换scriptlet取决于代码/逻辑的唯一目的。)
More than often this code is to be placed in a fullworthy Java class: (这些代码通常被置于一个完整的Java类中:)
If you want to invoke the same Java code on every request, less-or-more regardless of the requested page, eg checking if a user is logged in, then implement a filter and write code accordingly in doFilter()
method.
(如果要在每个请求上调用相同的 Java代码,不管请求的页面是否少于或多,例如检查用户是否已登录,然后在doFilter()
方法中实现过滤器并相应地编写代码。)
Eg: (例如:)
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. } }
When mapped on an appropriate <url-pattern>
covering the JSP pages of interest, then you don't need to copypaste the same piece of code overall JSP pages.
(当映射到适当的<url-pattern>
覆盖感兴趣的JSP页面时,您不需要在整个JSP页面中复制相同的代码片段。)
If you want to invoke some Java code to preprocess a request, eg preloading some list from a database to display in some table, if necessary based on some query parameters, then implement a servlet and write code accordingly in doGet()
method.
(如果要调用某些Java代码来预处理请求,例如,从数据库预加载某些列表以显示在某个表中,必要时根据某些查询参数,然后在doGet()
方法中实现servlet并相应地编写代码。)
Eg: (例如:)
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); } }
This way dealing with exceptions is easier.
(这种处理异常的方式更容易。)
The DB is not accessed in the midst of JSP rendering, but far before the JSP is been displayed. (在JSP渲染过程中不会访问DB,但是在JSP显示之前。)
You still have the possibility to change the response whenever the DB access throws an exception. (每当数据库访问引发异常时,您仍然可以更改响应。)
In the above example, the default error 500 page will be displayed which you can anyway customize by an <error-page>
in web.xml
. (在上面的示例中,将显示默认错误500页面,您可以通过web.xml
的<error-page>
自定义该<error-page>
。)
If you want to invoke some Java code to postprocess a request, eg processing a form submit, then implement a servlet and write code accordingly in doPost()
method.
(如果要调用某些Java代码来处理请求,例如处理表单提交,则实现servlet并在doPost()
方法中相应地编写代码。)
Eg: (例如:)
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."); //
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…