作者:蜗牛学院CTO李懿老师

​自从十年前的taglibs(如JSTL)和EL(表达语言,这些事情)诞生以来,在JSP中使用scriptlet(<% %>这些东西)的确是非常不鼓励的。

小脚本的主要缺点是:

1. 可重用性:不能重复使用scriptlet。

2. 可替换性:不能使scriptlet抽象。

3. OO能力:不能使用继承/组合。

4. Debuggability:如果scriptlet在中途抛出异常,那么你所得到的只是一个空白的页面。

5. 可测试性: scriptlet不能单元测试。

6. 可维护性:为了保持混合/混乱/重复的代码逻辑,需要更多的时间。

7. 可读性:在HTML代码中嵌入<%%>的小脚本让代码看上去更复杂、更难懂。

Oracle本身也建议使用JSP编码约定,以避免在(tag)类可以使用相同的功能时使用scriptlet。这里有几个相关的引用:

从JSP 1.2规范中,强烈建议在Web应用程序中使用JSP标准库(JSTL),以减少对页面中JSP脚本的需求

使用JSTL的页面通常更容易阅读和维护。

...

在可能的情况下,每当标签库提供相同的功能时,避免使用JSP脚本 这使得页面更容易阅读和维护,有助于将业务逻辑与表示逻辑分开,并将使页面更容易演进为JSP 2.0样式页面(JSP 2.0规范支持但不强调使用scriptlet)。

...

本着以采用模型视图控制器(MVC)设计模式来减少业务逻辑表示层之间耦合的精神,JSP脚本不应该用于编写业务逻辑。相反,如果需要,可以使用JSP脚本来将从客户端请求处理返回的数据(也称为“值对象”)转换为适当的客户端需求格式。这将更好地使用前端控制器servlet或自定义标签。

如何替换scriptlet完全取决于代码/逻辑的唯一目的。这个代码经常被放置在一个完整的Java类中:

· 如果要在每个请求上调用相同的 Java代码,不管请求的页面是多少,比如检查用户是否登录,则在方法中实现过滤器并相应地编写代码。例如:doFilter()

· publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throwsServletException, 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.

·     }

}

当映射到适当的<url-pattern>所关联的JSP页面时,您不需要在所有JSP页面上共享相同的代码片段。

· 如果要调用一些Java代码来预处理请求,例如从数据库中预先加载某些列表显示在某些表格中,如有必要,则根据某些查询参数,然后在方法中相应地实现servlet并编写代码doGet()。例如:

· protectedvoid doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, 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) {

· thrownewServletException("Retrieving products failed!", e);

·     }

}

这样处理异常更容易。在JSP渲染过程中,DB不被访问,但是在显示JSP之前,当DB访问引发异常时,您仍然可以更改响应。

在上面的例子中,默认的错误500页面将被显示,你可以通过一个<error-page>in web.xml。

如果要调用一些Java代码来处理请求,例如处理表单提交,则在方法中实现一个servlet并相应地编写代码doPost()。

· 例如:

· protectedvoid doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, 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.

·     }

}

通过这种方式处理不同结果页面的目的地更容易:重新显示在一个错误的情况下验证错误的形式(在这个特殊的例子,你可以使用重新显示${message}在EL),或只是把到所需的目标页面在成功的情况下验证。

· 如果要调用一些Java代码来控制请求和响应的执行计划和/或目标,则根据MVC的前端控制器模式实现一个servlet。例如:

· protectedvoid service(HttpServletRequest request, HttpServletResponse response) throwsServletException, 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) {

· thrownewServletException("Executing action failed.", e);

·     }

}

或者只是采用像JSF,Spring MVC,Wicket等这样的MVC框架,所以你只需要一个JSP / Facelets页面和一个Javabean类,而不需要一个自定义的servlet。

· 如果要调用一些Java代码来控制 JSP页面中的流程,那么就需要像JSTL内核那样获取一个(现有的)流控制taglib 。例如List<Product>:

· <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

· ...

· <table>

· <c:forEachitems="${products}"var="product">

· <tr>

· <td>${product.name}</td>

· <td>${product.description}</td>

· <td>${product.price}</td>

· </tr>

· </c:forEach>

</table>

使用适合所有这些HTML的XML样式标签,代码比一堆具有不同打开和关闭括号的“script”属于更好的可读性(因此可维护性更好)。一个简单的帮助是配置您的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,它已经能够使用小脚本。这样你就被自动地强制做“正确的方式”。

· 如果要调用一些Java代码来访问并在JSP页面中显示 “后端”数据,则需要使用EL(表达式语言)这些东西。提交的输入值,例如重新显示:

<inputtype="text"name="foo"value="${param.foo}"/>

该${param.foo}显示器的结果request.getParameter("foo")。

· 如果要在JSP页面(通常是方法)中直接调用一些实用程序 Java代码public static,那么需要将它们定义为EL函数。JSTL中有一个标准函数taglib,可以轻松地自己创建函数。以下是JSTL如何fn:escapeXml有效防止XSS 攻击的示例。

· <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

· ...

<inputtype="text"name="foo"value="${fn:escapeXml(param.foo)}"/>

请注意,XSS敏感性与Java / JSP / JSTL / EL /无关,这个问题需要在你开发的每个 Web应用程序中考虑。scriptlet的问题在于它不提供内置的预防方法,至少不使用标准的Java API。JSP的继任者Facelets已经隐式HTML转义,所以大家不需要担心Facelets中的XSS漏洞。

挖矿搬砖不如IT码农,轻松转行还看蜗牛学院。

蜗牛学院 专注于IT职业教育,轻松转行,简学易懂;免费试学,亲身体验;商业项目亲自操刀,与名企零距离接触;应届生就业薪资6000起,年薪10万不是事,涨幅绝比房价高。

转载于:https://www.cnblogs.com/woniuxy/p/7419242.html

避免在JSP中写java代码相关推荐

  1. java代码在jsp中怎么写_在jsp中写java代码

    该服务器上的所有的访问者的所有 jsp 页面 D.该服务器上的所有的访问者的所有 jsp 页面和 Java 程序 6.在 JSP 中调用 JavaBean 时不会用到的标记是( )...... jav ...

  2. 如何在jsp里面写java代码

    jsp和html相比,最显著的优势就在于,jsp里面可以写java代码,但是html中不能. 那么如何在jsp中写java代码呢! jsp中写java代码有如下三种方式: <%! %>,这 ...

  3. JSP中嵌入java代码方式以及指令

    JSP中嵌入java代码的三种方式: (1)声明变量或方法 :  <%! 声明; %> :慎重使用,因为此方法定义的是全局变量 (2)java片段(scriptlet):  <% j ...

  4. jsp里写java代码报错,jsp里写java代码报错

    jsp里写java代码报错 [2021-02-11 06:42:03]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace("/ ...

  5. jsp中的java代码怎样调试

    前言 在网络技术中基于浏览器的B/S结构无论在PC端还是手机端都充当着至关重要的角色. PC端自不必说,手机中很多应用虽然是以APP的形式存在,但它采用的还是B/S结构.如今日头条.微信的朋友圈等,这 ...

  6. 如何在jsp中写一个java方法

    一般用<%!  %>在jsp中写java方法 代码如下: <%@ page language="java" import="java.util.*,ja ...

  7. vscode写java没有提示_VS Code报错Language Support for Java(TM)插件显示需要JDK11 写java代码没有提示...

    鉴于IDEA的打开速度(电脑的垃圾),平常刷LeetCode都是在VSCode上,结果这几天老是打开给我报错 Java 11 or more recent is required to run. Pl ...

  8. java el表达式 导航规则_诺禾:在jsp里面如何不写java代码展示数据(EL表达式的使用)...

    EL表达式可以简化jsp中写的java代码 在jsp里面如何不写java代码展示数据(EL表达式的使用) 在jsp里面如何不写java代码展示数据(EL表达式的使用) 在jsp里面如何不写java代码 ...

  9. jsp页面中嵌入java代码

    1.jsp页面中嵌入java代码 jsp的脚本元素 jsp的指令元素 jsp的动作元素 1.1 jsp的脚本元素(直接嵌入java代码) 第一种:表达式(expression)形式:<%= %& ...

最新文章

  1. 在SIFT和SURF之后,有哪些比较新的且具有一定影响力的自然图像配准算法?
  2. go实现重新给metric打标签上传到prometheus_案例分析|云原生监控Prometheus对样本rate计算,出现标签重复?...
  3. java窗口坐标_如何在Java中获取窗口外部的鼠标单击坐标
  4. python None与Null
  5. 每日一笑 | 为什么英语老师让我们养成背单词的习惯?
  6. 【渝粤题库】广东开放大学 C语言程序设计 形成性考核
  7. leetcode 674. 最长连续递增序列
  8. 列举python中常用的数据类型_Python基础知识 变量和简单数据类型
  9. dubbo 注册中心zookeeper 手册
  10. 玩转Google开源C++单元测试框架Google Test系列
  11. 基于JAVA+SpringMVC+MYSQL的球队管理系统
  12. 初步看,我要在公司赚取更多的工资,钱多活少离家近
  13. 论文阅读笔记(四)——ESPNetV2:A Light-weight Power Efficient and General Purpose Convolutional Neural Network
  14. unity3d改变物体的中心位置_Unity3d粒子特效:制作火焰效果
  15. 基于FairMOT的车流量统计
  16. R语言读取(加载)txt格式数据为dataframe、按照指定字段(数据列)对dataframe进行升序排序(ascending)、返回行索引的位置向量
  17. 对于多人联机游戏中 游戏房间实现的想法
  18. 618啦,你的钱包又被盯上啦!
  19. github生成密钥步骤
  20. 快速上手 ClickHouse

热门文章

  1. PowerShell 2.0管理事件日志(一)查看和读取事件日志
  2. SQL语句 goto
  3. windows 如何安装oracle 补丁包,Windows Server 2003 上安装 Oracle10g(10.2.0.1)并升级 至补丁(10.2.0.4) 图解...
  4. 对称加密和非对称加密
  5. 68-95-99规则–以普通英语解释正态分布
  6. snapd_snapd使管理Nextcloud变得轻而易举
  7. travis ci_如何使用Travis CI和GitHub进行Web开发工作流程
  8. 头条小视频和西瓜视频signature签名算法
  9. 2021年浙软夏令营预推免面经
  10. java培训要学习多久?