From a16306f433cf4b1880df4d7a60a7ab4b2621d3a6 Mon Sep 17 00:00:00 2001 From: lyzzzz Date: Tue, 15 Sep 2015 20:13:29 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E2=80=9CDeclare=5Farray=5Fin=5FJava=E2=80=9D=E3=80=82=E5=A6=82?= =?UTF-8?q?=E6=9C=89=E8=AF=AD=E6=B3=95=E4=B8=8D=E8=B6=B3=E8=AF=B7=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=3D=20=3D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + contents/Declare_array_in_Java.md | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 contents/Declare_array_in_Java.md diff --git a/README.md b/README.md index 3a6928c..c49524f 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ stackoverflow-Java-top-qa * [JavaBean 到底是什么](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/what-is-a-javabean-exactly.md) * [wait()和sleep()的区别](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/difference-between-wait-and-sleep.md) * [能否在一个构造器( `constructor` )中调用另一个构造器](http://stackoverflow.com/questions/285177/how-do-i-call-one-constructor-from-another-in-java) +* [如何声明一个数组](http://stackoverflow.com/questions/1200621/declare-array-in-java) > 编程技巧 diff --git a/contents/Declare_array_in_Java.md b/contents/Declare_array_in_Java.md new file mode 100644 index 0000000..38c09ed --- /dev/null +++ b/contents/Declare_array_in_Java.md @@ -0,0 +1,24 @@ +##在 Java 里定义一个数组 + +###问题 +如何在 Java 里定义一个数组? + +###回答 +你可以只是声明一个数组,也可以用数组初始化的形式(但是只有在声明并马上赋值的时候才可以用这种方式,数组初始化的形式并不能用于对数组进行再次赋值) + +对于 基本类型 数组来说: +```java +int[] myIntArray = new int[3]; +int[] myIntArray = {1,2,3}; +int[] myIntArray = new int[]{1,2,3}; +``` + +对于 类 来说,比如String,以下这几种的方式是一样的: +```java +String[] myStringArray = new String[3]; +String[] myStringArray = {"a","b","c"}; +String[] myStringArray = new String[]{"a","b","c"}; +``` + +stackoverflow原址: +http://stackoverflow.com/questions/1200621/declare-array-in-java \ No newline at end of file From c44eb4882e562a5b332eff8493c321990abc5614 Mon Sep 17 00:00:00 2001 From: lyzzzz Date: Tue, 15 Sep 2015 20:19:13 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E6=AD=A3readme=E3=80=82=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E5=B7=B2=E7=BF=BB=E8=AF=91=E9=97=AE=E9=A2=98=E2=80=9C?= =?UTF-8?q?=E5=A6=82=E4=BD=95=E5=A3=B0=E6=98=8E=E6=95=B0=E7=BB=84=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c49524f..9c4b42d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,6 @@ stackoverflow-Java-top-qa - [Initialization of an ArrayList in one line](http://stackoverflow.com/questions/1005073/initialization-of-an-arraylist-in-one-line) - [Java inner class and static nested class](http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class) - ['Must Override a Superclass Method' Errors after importing a project into Eclipse](http://stackoverflow.com/questions/1678122/must-override-a-superclass-method-errors-after-importing-a-project-into-eclips) -- [Declare array in Java?](http://stackoverflow.com/questions/1200621/declare-array-in-java) - [Fastest way to determine if an integer's square root is an integer](http://stackoverflow.com/questions/295579/fastest-way-to-determine-if-an-integers-square-root-is-an-integer) - [How to fix: Unsupported major.minor version 51.0 error?](http://stackoverflow.com/questions/10382929/how-to-fix-unsupported-major-minor-version-51-0-error) - [What is reflection and why is it useful?](http://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful) From a9150ceb0893f474b0298760dfe3a0e805c8a453 Mon Sep 17 00:00:00 2001 From: lyzzzz Date: Fri, 18 Sep 2015 00:38:24 +0800 Subject: [PATCH 3/3] add "How_to_avoid_Java_code_in_JSP_files" fix README.md --- README.md | 4 +- .../How_to_avoid_Java_code_in_JSP_files.md | 173 ++++++++++++++++++ 2 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 contents/How_to_avoid_Java_code_in_JSP_files.md diff --git a/README.md b/README.md index 9c4b42d..56ac87e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ stackoverflow-Java-top-qa * [JavaBean 到底是什么](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/what-is-a-javabean-exactly.md) * [wait()和sleep()的区别](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/difference-between-wait-and-sleep.md) * [能否在一个构造器( `constructor` )中调用另一个构造器](http://stackoverflow.com/questions/285177/how-do-i-call-one-constructor-from-another-in-java) -* [如何声明一个数组](http://stackoverflow.com/questions/1200621/declare-array-in-java) +* [如何声明一个数组](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/Declare_array_in_Java.md) +* [如何避免在JSP文件中使用Java代码](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/How_to_avoid_Java_code_in_JSP_files.md) > 编程技巧 @@ -61,7 +62,6 @@ stackoverflow-Java-top-qa - [Is there a unique Android device ID?](http://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id) - [Why does this code using random strings print “hello world”?](http://stackoverflow.com/questions/15182496/why-does-this-code-using-random-strings-print-hello-world) - [How can I create an executable jar with dependencies using Maven?](http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven) -- [How to avoid Java code in JSP files?](http://stackoverflow.com/questions/3177733/how-to-avoid-java-code-in-jsp-files) - [Why is executing Java code in comments with certain Unicode characters allowed?](http://stackoverflow.com/questions/30727515/why-is-executing-java-code-in-comments-with-certain-unicode-characters-allowed) - [Dealing with “java.lang.OutOfMemoryError: PermGen space” error](http://stackoverflow.com/questions/88235/dealing-with-java-lang-outofmemoryerror-permgen-space-error) - [“implements Runnable” vs. “extends Thread”](http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread) diff --git a/contents/How_to_avoid_Java_code_in_JSP_files.md b/contents/How_to_avoid_Java_code_in_JSP_files.md new file mode 100644 index 0000000..c95cc31 --- /dev/null +++ b/contents/How_to_avoid_Java_code_in_JSP_files.md @@ -0,0 +1,173 @@ +##如何避免在JSP文件中使用Java代码 + +###问题 +如何避免在JSP文件中使用Java代码? + +我对Java EE不是很熟悉,我知道类似如下的三行代码 +```jsp +<%= x+1 %> +<%= request.getParameter("name") %> +<%! counter++; %> +``` +这三行代码是学校教的老式代码。在JSP 2,存在一些方法可以避免在JSP文件中使用Java代码。有人可以告诉我在JSP 2中如何避免使用Java代码吗,这些方法该如何使用? + +###回答 +在大约十年前,taglibs(比如JSTL)和EL(EL表达式,`${}`)诞生的时候,在JSP中使用scriptlets(类似`<% %>`)这种做法,就确实已经是不被鼓励使用的做法了。 + +scriptlets 主要的缺点有: +1. **重用性** :你不可以重用scriptlets +2. **可替换性** :你不可以让scriptlets抽象化 +3. **面向对象能力** :你不可以使用继承或组合 +4. **调试性** :如果scriptlets中途抛出了异常,你只能获得一个空白页 +5. **可测试性** :scriptlets不能进行单元测试 +6. **可维护性** :(这句有些词语不确定)需要更多的时间去维护混合的/杂乱的/冲突的 代码逻辑 + +Oracle自己也在 [JSP coding conventions](http://www.oracle.com/technetwork/articles/javase/code-convention-138726.html)一文中推荐在功能可以被标签库所替代的时候避免使用scriptlets语法。以下引用它提出的几个观点: + +> 在JSP 1.2规范中,强烈推荐使用JSTL来减少JSP scriptlets语法的使用。一个使用JSTL的页面,总得来说会更加地容易阅读和维护。 + +>... + +>在任何可能的地方,当标签库能够提供相同的功能时,尽量避免使用JSP scriptlets语法。这会让页面更加容易阅读和维护,帮助将 业务逻辑 从 表现层逻辑 中分离,也会让页面往更符合JSP 2.0风格的方向发展(JSP 2.0规范中,支持但是极大弱化了JSP scriptlets语法) + +>... + +>本着适应 模型-显示层-控制器(MVC) 设计模式中关于减少业务逻辑层与显示层之间的耦合的精神,**JSP scriptlets语法不应该**被用来编写业务逻辑。相应的,JSP scriptlets语法在传送一些服务端返回的处理客户端请求的数据(也叫做 声明对象?。这里翻译得不清楚)的时候会被使用。尽管如此,使用一个controller servlet来处理或者用自定义标签来处理会更好。 + +----------- + +**如何替换scriptlets语句,取决于代码/逻辑的目的。更常见的是,被替换的语句会被放在另外的一些更值得放的Java类里**(这里翻译得不一定清楚) + +* 如果你想在每个请求运行**相同的**Java代码,less-or-more regardless of the requested page(不会翻译),比如说 检查一个用户是否在登录状态,就要实现一个 过滤器,在doFilter()方法中编写正确的代码,例如 + +```java +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. + } +} +``` +当你在``中做好恰当的地址映射,覆盖所有应该被覆盖的JSP文件,也就不需要再JSP文件中添加这些相同的Java代码 + +---------------- + +* 如果你想执行一些Java代码来**预处理**一个请求,例如,预加载某些从数据库加载的数据来显示在一些表格里,可能还会有一些查询参数,那么,实现一个Servlet,在doGet()方法里编写正确的代码,例如 + +```java +protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + try { + List 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); + } +} +``` +这个方法能够更方便地处理异常。The DB is not accessed in the midst of JSP rendering, but far before the JSP is been displayed.(不会翻译)在数据库抛出异常的时候,你还是有改变response的可能。在上面的例子,默认的500页会显示,你还可以改变`web.xml`的``来自定义异常处理错误页。 + +---------- + +* 如果你想执行一些Java代码来**后置处理(postprocess)**一个请求,例如处理表单提交,那么,实现一个Servlet,在doPost()里写上正确的代码: + +```java +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."); // 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. + } +} +``` +这个处理不同目标结果页的方法会比原来更加简单: 可以显示一个带有表单验证错误提示的表单(在这个特别的例子中,你可以用EL表达式`${message}`来显示错误提示),或者仅仅跳转到成功的页面 + +--------- + +* 如果你想执行一些Java代码来**控制**执行计划(control the execution plan) 和/或 request和response的目标,用[MVC模式](http://stackoverflow.com/questions/3541077/design-patterns-web-based-applications/3542297#3542297)实现一个Servlet,例如: +```java +protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, 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) { + throw new ServletException("Executing action failed.", e); + } +} +``` +或者使用一些MVC框架例如[JSF](http://stackoverflow.com/tags/jsf/info), [Spring MVC](http://stackoverflow.com/tags/spring-mvc/info), [Wicket](http://stackoverflow.com/tags/wicket/info) end up with just a JSP/Facelets page and a Javabean class without the need for a custom servlet.(不知道如何翻译准确) + +--------- + +* 如果你想执行一些Java代码来**控制JSP页面的执行流程(control the flow inside a JSP page)**,那么你需要使用一些(已经存在的)流程控制标签库,比如[JSTL core](http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/c/tld-summary.html),例如,在一个表格显示`List` + +```java +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +... + + + + + + + + +
${product.name}${product.description}${product.price}
+``` +这些XML风格的标签可以很好地适应HTML代码,代码变得更好阅读(也因此更好地维护),相比于杂乱无章的scriptlets 的分支大括号(Where the heck does this closing brace belong to?"(到底这个结束大括号是属于哪个代码段的?))。一个简单的设置可以配置你的Web程序让在使用scriptlets 的时候自动抛出异常 + +```xml + + + *.jsp + true + + +``` + +在JSP的继承者[Facelets](http://stackoverflow.com/tags/facelets/info)里(Java EE提供的MVC框架[JSF](http://stackoverflow.com/tags/jsf/info)),已经**不**可能使用scriptlets语法了。这是一个让你强制使用“正确的方法”的方法 + +----------- + +* 如果你想执行一些Java代码来在JSP中 **访问和显示** 一些“后端”数据,你需要使用EL(表达式),`${}`,例如,显示已经提交了的数值: + +```jsp + +``` + +`${param.foo}`会显示`request.getParameter("foo")`这句话的输出结果。 + +-------------- + +* 如果你想在JSP直接执行一些工具类Java代码(典型的,一些public static方法),你需要定义它,并使用EL表达式函数。这是JSTL里的标准函数标签库,但是你也可以[轻松地创建自己需要的功能](http://docs.oracle.com/javaee/5/tutorial/doc/bnahq.html#bnaiq),下面是一个使用有用的`fn:escapeXml`来避免XSS攻击的例子。 + +```java +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +... + +``` + +注意,XSS并不是Java/JSP/JSTL/EL/任何技术相关的东西,这个问题是**任何**Web应用程序都需要关心的问题,scriptlets 并没有为这个问题提供良好的解决方案,至少没有标准的Java API的解决方案。JSP的继承者Facelets内含了HTML转义功能,所以在Facelets里你不用担心XSS攻击的问题。 + +See Also: +* [JSP, Servlet, JSF的不同点在哪里?](http://stackoverflow.com/questions/2095397/what-is-the-difference-between-jsf-servlet-and-jsp/2097732#2097732) +* [Servlet, ServletContext, HttpSession 和 HttpServletRequest/Response 是如何工作的?](http://stackoverflow.com/questions/3106452/java-servlet-instantiation-and-session-variables/3106909#3106909) +* [JSP, Servlet and JDBC的基本MVC例子](http://stackoverflow.com/questions/5003142/jsp-using-mvc-and-jdbc) +* [Java Web应用程序中的设计模式](http://stackoverflow.com/questions/3541077/design-patterns-web-based-applications/) +* [JSP/Servlet中的隐藏功能](http://balusc.blogspot.com/2010/01/hidden-features-of-jspservlet.html) + + +stackoverflow原址:http://stackoverflow.com/questions/3177733/how-to-avoid-java-code-in-jsp-files \ No newline at end of file