当前位置: 首页 > 编程日记 > 正文

避免在JSP中写java代码

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

322300006333a037e659

​自从十年前的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

相关文章:

爱情也许是最忧伤的童话

也许爱情是一部忧伤的童话 惟其遥远与真实 惟其不可触摸与欠缺 方可成就起璀璨与神圣 或许&#xff0c;只有在难得最远的时候&#xff0c; 才能把曾经走过的那段日子 看得最真切、最清楚 放弃一个很爱你的人&#xff0c;并不痛苦 放弃一个你很爱的人&#xff0c;那才痛苦 爱…

Docker最全教程——从理论到实战(六)

Docker最全教程——从理论到实战&#xff08;六&#xff09; 原文:Docker最全教程——从理论到实战&#xff08;六&#xff09;托管到腾讯云容器服务 托管到腾讯云容器服务&#xff0c;我们的公众号“magiccodes”已经发布了相关的录屏教程&#xff0c;大家可以结合本篇教程一起…

c#中分割字符串的几种方法

第一种方法&#xff1a;打开vs.net新建一个控制台项目。然后在Main()方法下输入下面的程序。 string s"abcdeabcdeabcde"; string[] sArrays.Split(c); foreach(string i in sArray) Console.WriteLine(i.ToString()); 输出下面的结果:ab deab deab de 我们看到了结果…

对相机所看的视角截屏保存为图片

对相机所看的视角截屏保存为图片&#xff1a; 1 using UnityEngine;2 using System.Collections;3 using UnityEngine.UI;4 /// <summary>5 /// 对相机截图6 /// </summary>7 public class Jietu : MonoBehaviour {8 9 public Camera camera; 10 Texture2D…

fsum函数测试以及分析

#include <stdio.h> #include <stdlib.h> #include <string.h>#define BUFSIZE 256//这是一句预定义&#xff0c;定义BUFSIZE的值是100&#xff0c;是缓冲空间的大小,作为数组的。int main(int argc, char *argv[]) //第一个int argc&#xff0c;是记录你输入…

oracle学习总结二(转义字符)

1、oracle 特殊字符 转义关键词&#xff1a; oracle 转义 环境&#xff1a;oracle 9i plsql在plsql里边执行:update userinfo set pageurlmyjsp?page1&pagesize10 where idtest这条sql语句往数据库的pageurl字段放进去了一…

C语言——冒泡法排序应用

#include <stdio.h> #include <stdlib.h> int main()/*有int main 就会有return 0;如果是void main ,就不用加上return 0了 */ {int i,j,temp;/*待会要用到&#xff0c;所以先定义,因为输入的都是整数&#xff0c;所以用int整数型*/int a[10];/*定义一个一维整型数…

2017 Multi-University Training Contest 3 hdu 6063

HDU 6063 思路&#xff1a; AC代码&#xff1a; #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "m…

[学习]GridView 学习集合 -- GridView中使用超链接的技巧

GridView中使用超链接的技巧 数据绑定方式有两种&#xff0c;如下示例&#xff1a; Eval方式 &#xff1c;%# Eval("id") %&#xff1e; Bind方式 &#xff1c;%# Bind("id","~/info.aspx?id{0}") %&#xff1e; 推荐使用第一种方式&#xff0c…

C# http 性能优化500毫秒到 60 毫秒

来源&#xff1a;https://www.cnblogs.com/hnsongbiao/p/9815808.html 偶然发现 C# 的 HttpRequest 要比 Chrome 请求同一Url 慢好多。C# HttpRequest 要500毫秒 而Chrome 只需要 39ms。 后来 整理 各种方法做了优化 HttpWebRequest request WebRequest.Create(address) as H…

一个计算机高手的成长(转)

这些日子我一直在写一个实时操作系统内核&#xff0c;已有小成了&#xff0c;等写完我会全部公开&#xff0c;希望能 够为国内IT的发展尽自己一份微薄的力量。最近看到很多学生朋友和我当年一样没有方向 &#xff0c;所以把我的经历写出来与大家共勉&#xff0c;希望能给刚如行…

正则表达式整理

1.特殊字符 ^匹配输入字符串的开始位置$匹配输入字符串的结尾位置( )标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符&#xff0c;请使用 \( 和 \)。* 匹配前面的子表达式零次或多次。要匹配 * 字符&#xff0c;请使用 \*。匹配前面的子表达式一…

CSS-hover

1. padding:0 10px; 表示上下边距是0&#xff0c;左右边距是10. 2. padding:0 10px 0 10px&#xff1b; 上-右-下-左。&#xff08;顺时针方向&#xff09; 3. .pg-header .menu:hover&#xff1b; 表示只要鼠标移动到当前标签上时&#xff0c;就会应用这个下面所定义的样式。 …

Error原生类型

•表示错误对象 –EvalError, URIError, RangeError, etc. •捕获方式&#xff1a; –try { …throw new Error(…) } catch(e) { … } –理论上可以throw出任意对象 •Error对象IE和FireFox公有属性 –message&#xff1a;错误信息Error浏览器特定属性 •IE&#xff1a; –des…

求矩阵两条对角线元素之和

#include <stdio.h> #include <stdlib.h>int main() {int a[3][3];//定义一个二维数组&#xff0c;三行三列&#xff0c;a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],a[3][0],a[3][1],a[3][2]int i,j,sum0;printf("请输入9个数据给数组赋值:\n");f…

关于Java中各种修饰符与访问修饰符的说明

关于Java中各种修饰符与访问修饰符的说明 类&#xff1a; 访问修饰符 修饰符 class 类名称extends 父类名称 implement 接口名称 &#xff08;访问修饰符与修饰符的位置可以互换&#xff09;访问修饰符 名称 说明 备注 public可以被所有类访问&#xff08;使用&#xff0…

buffer IO和direct IO

最近在看很多框架&#xff0c;redis&#xff0c;kafka等底层都涉及到文件IO操作的效率问题&#xff0c;所以查了些资料&#xff0c;看到这篇文章讲的比较明白些&#xff0c;贴出来留存。 链接地址&#xff1a; https://www.ibm.com/developerworks/cn/linux/l-cn-directio/转载…

python 列表使用

下面实现的类似于java中的数组&#xff1a; names[-2]表示实现倒数的第2个参数 names[-3,-1]表示实现-3到-1的值不包含-1 增删改查 下面代码实现列表的增删改查功能&#xff1a; 复制copy 深copy:这个可以copy全部的参数列表&#xff08;一般不用&#xff09;。 For循环打印列表…

c语言——求单词个数

#include <stdio.h> #include <stdlib.h>int main() {char str[20];//定义一个字符型一维数组&#xff0c;长度为20int i,num;printf("请输入一行英文:\n");//提示语句gets(str);//输入一个字符串给字符数组strnum str[0]! ? 1:0;//? : 是条件运算符…

C# 各种进制之间相互转换 [ZT]

MessageBox.Show(Convert.ToString(12345, 2)); //10进制转换为2进制MessageBox.Show(Convert.ToString(12345, 8)); //10进制转换为8进制MessageBox.Show(Convert.ToString(12345, 16)); //10进制转换为16进制MessageBox.Show(Convert.ToInt32("1100", 2).ToStri…

慕课《深入理解计算机系统》袁林枫老师章节测试1-9

1以下有关冯.诺依曼结构思想的叙述中&#xff0c;错误的是&#xff08; C &#xff09;。 A.计算机内部以二进制形式表示指令和数据 B.程序由指令构成&#xff0c;计算机能自动执行程序中一条一条指令 C.指令和数据都放在存储器中&#xff0c;两者在形式上有差别&#xff08…

WCF 和 ASP.NET Web API

地址&#xff1a;https://docs.microsoft.com/zh-cn/dotnet/framework/wcf/wcf-and-aspnet-web-api WCF 是 Microsoft 为生成面向服务的应用程序而提供的统一编程模型。 借助这一模型&#xff0c;开发人员可以构建既能跨平台与现有投资集成又能与现有投资交互的安全、可靠的事务…

php中操作mysql的函数库

发现php中的mysql库是一个函数库 而不是一个类库 使用面向过程的形式组织。mysql_affected_rows -- 取得前一次 MySQL 操作所影响的记录行数 mysql_change_user -- 改变活动连接中登录的用户 mysql_client_encoding -- 返回字符集的名称 mysql_close -- 关闭 MySQL 连接 mysq…

Firetruck UVA - 208

DFS并查集 如果只用DFS的话会超时&#xff0c;用并查集剪枝&#xff0c;和起点终点不联通的点就不用跑了 这题有好多人写了博客&#xff0c;但是我觉得我的代码写的比较通俗易懂所以就贴上来了&#xff0c;我觉得我写代码的目标就是让任何人都能看懂&#xff0c;越小白越好&…

MCSE2003学习之三

安装&#xff37;&#xff29;&#xff2e; &#xff38;&#xff30;&#xff38;&#xff30;的系统中&#xff0c;&#xff13;&#xff12;位的系统最大支持的&#xff32;&#xff21;&#xff2d;为&#xff14;&#xff27;&#xff0c;而&#xff16;&#xff14;位的…

【LeetCode】230#二叉搜索树中第K小的元素

题目描述 给定一个二叉搜索树&#xff0c;编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。 说明&#xff1a; 你可以假设 k 总是有效的&#xff0c;1 ≤ k ≤ 二叉搜索树元素个数。 示例 1: 输入: root [3,1,4,null,2], k 13/ \1 4\2 输出: 1 示例 2: 输入: root …

runaway深度递归函数测试及相关汇编指令

这是一个深度递归的例子。 #include <stdio.h> #include <stdlib.h>int recurse(int x) {int a[1<<15]; /* 4 * 2^15 64 KiB */printf("x %d. a at %p\n", x, a); a[0] (1<<14)-1;a[a[0]] x-1;if (a[a[0]] 0)return -1;return rec…

codeforce843B Interactive LowerBound

题意&#xff1a;交互式的题&#xff0c;给你n,s, x&#xff0c;链表元素有n个&#xff0c;开始的位置是s&#xff0c;每次询问输入数组的下标&#xff0c;可以知道对应链表上的数和链表下一个数的位置&#xff0c;只能询问2000次&#xff0c;要找到第一个大于等于x的数 题解&a…

[原]SSL 开发简述(Delphi)

一、 简介 现在网上有关SSL的资料较多的是基于VC开发&#xff0c;Delphi的SSL开发资源很少。 本文主要使用OpenSSL为基础&#xff0c;讲述SSL的有关开发流程。OpenSSL功能非常丰富&#xff0c;具体可以去她的官方网看看。可惜没有中文说明。 OpenSSL&#xff1a;htt…

如何每天自动备份 SourceSafe (转)

在Microsoft Visual SourceSafe中提到管理员应该每天或者至少每周备份一次SourceSafe中的内容。这里&#xff0c;我们利用现有的工具实现每天自动备份SourceSafe中的内容。<?XML:NAMESPACE PREFIX O />1. 用到的工具a. ssarc.exe. ssarc.exe是随着SourceSafe提供…