Web基础知识(14)- JSP (六) | JSP 异常处理、JSP 调试、JSP 国际化
1. JSP 异常处理
JSP 开发作为 Java 开发的一个子集,对异常的处理自然遵守 Java 异常的定义方式和基本处理规则,Java 异常处理参考 “Java基础知识(7)- Java 异常处理(一)” 和 “Java基础知识(8)- Java 异常处理(二)”。
JSP 依赖于 Servlet,JSP 只是在 Servlet 的基础上做了进一步封装,所以这里把 JSP 异常 和 Servlet 异常当成同一类型的异常。
JSP 处理异常的方式:
(1) 使用 web.xml 定义 Error Page
(2) 使用 Exception 对象
(3) 使用 try … catch块
(4) 使用 JSTL 标签
这里以 IDEA + Maven 创建的 WebBasic 项目为例( Web基础知识(2)- Java Servlet (二) ),演示以上四种 JSP 异常处理方式。
1) 使用 web.xml 定义 Error Page
(1) 修改 web.xml
1 <web-app> 2 3 ... 4 5 <error-page> 6 <error-code>404</error-code> 7 <location>/error/404.html</location> 8 </error-page> 9 10 </web-app>
(2) 创建 src/main/webapp/error/404.html
1 <html> 2 <head> 3 <title>404 Error</title> 4 </head> 5 <body> 6 <h2>404 Error</h2> 7 <p>Not Found Page</p> 8 </body> 9 </html>
访问一个不存在的路径,比如 http://localhost:9090/notexists, 显示 404.html
2) 使用 Exception 对象
(1) 创建 src/main/webapp/error/showError.jsp
1 <%@ page isErrorPage="true" %> 2 <html> 3 <head> 4 <title>Error Page</title> 5 </head> 6 <body> 7 <h1>Error Page</h1> 8 <p>Message: <%=exception.getMessage() %></p> 9 <p>Error: <%=exception.toString() %></p> 10 <p></p> 11 </body> 12 </html>
(2) 创建 src/main/webapp/test_error.jsp
1 <%@ page errorPage="error/showError.jsp" %> 2 <html> 3 <head> 4 <title>Test Error Example</title> 5 </head> 6 <body> 7 <% 8 int x = 1/0; 9 %> 10 </body> 11 </html>
访问 http://localhost:9090/test_error.jsp, 显示:
Error Page
Message: / by zero
Error: java.lang.ArithmeticException: / by zero
3) 使用 try … catch 块
想要将异常处理放在一个页面中,并且对不同的异常进行不同的处理,那么就需要使用 try … catch 块。
创建 src/main/webapp/test_error2.jsp
1 <%@ page contentType="text/html;charset=UTF-8" language="java"%> 2 <html> 3 <head> 4 <title>Test Error2 Example</title> 5 </head> 6 <body> 7 <h1>Error2 Page</h1> 8 <% 9 try { 10 int i = 1 / 0; 11 out.println("The answer is " + i); 12 } catch (Exception e) { 13 out.println("Message: " + e.getMessage()); 14 out.println("Error: " + e.toString()); 15 } 16 %> 17 </body> 18 </html>
访问 http://localhost:9090/test_error2.jsp, 显示:
Error2 Page
Message: / by zero
Error: java.lang.ArithmeticException: / by zero
4) 使用 JSTL 标签
Maven 项目 WebBasic 里要使用 JSTL,需要先导入 JSTL 依赖包。
(1) 修改 pom.xml, 导入 JSTL 依赖包
1 <project ... > 2 3 <dependencies> 4 ... 5 6 <!-- https://mvnrepository.com/artifact/javax.servlet/jstl --> 7 <dependency> 8 <groupId>javax.servlet</groupId> 9 <artifactId>jstl</artifactId> 10 <version>1.2</version> 11 </dependency> 12 13 ... 14 </dependencies> 15 16 </project>
(2) 创建 src/main/webapp/error/showError2.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ page isErrorPage="true" isELIgnored="false" %> 3 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 4 <html> 5 <head> 6 <title>Error3 Page</title> 7 </head> 8 <body> 9 <h1>Error3 Page</h1> 10 <table width="100%" border="1"> 11 <tr valign="top"> 12 <td width="40%"><b>Error:</b></td> 13 <td>${pageContext.exception}</td> 14 </tr> 15 <tr valign="top"> 16 <td><b>URI:</b></td> 17 <td>${pageContext.errorData.requestURI}</td> 18 </tr> 19 <tr valign="top"> 20 <td><b>Status code:</b></td> 21 <td>${pageContext.errorData.statusCode}</td> 22 </tr> 23 <tr valign="top"> 24 <td><b>Stack trace:</b></td> 25 <td> 26 <c:forEach var="trace" items="${pageContext.exception.stackTrace}"> 27 <p>${trace}</p> 28 </c:forEach> 29 </td> 30 </tr> 31 </table> 32 </body> 33 </html>
(3) 修改 src/main/webapp/test_error.jsp
1 <%@ page errorPage="error/showError2.jsp" %> 2 <html> 3 <head> 4 <title>Test Error Example</title> 5 </head> 6 <body> 7 <% 8 int x = 1/0; 9 %> 10 </body> 11 </html>
访问 http://localhost:9090/test_error.jsp, 显示:
Error: java.lang.ArithmeticException: / by zero
URI: /test_error.jsp
Status code: 500
Stack trace:
org.apache.jsp.test_005ferror_jsp._jspService(test_005ferror_jsp.java:70)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
...
2. JSP 调试
1) 使用 System.out.println()
System.out.println()可以很方便地标记一段代码是否被执行。使用范围包括 Servlets,JSP,RMI,EJB's,Beans,类和独立应用。
用 System.out 进行输出不会对应用程序的运行流程造成重大的影响,这个特点在定时机制非常重要的应用程序中就显得非常有用了。
System.out.println() 的语法:
System.out.println("Debugging message");
示例1:
1 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <html> 3 <head><title>Debug</title></head> 4 <body> 5 <c:forEach var="counter" begin="1" end="10" step="1" > 6 <c:out value="${counter-5}"/></br> 7 <% 8 System.out.println( "counter = " + pageContext.findAttribute("counter") ); 9 %> 10 </c:forEach> 11 </body> 12 </html>
在 Tomcat 服务器 logs 目录下的 stdout.log 文件中有如下内容:
counter=1
counter=2
counter=3
...
使用这种方法可以将变量和其它的信息输出至系统日志中。
2) 使用 JDB Logger
J2SE 日志框架可为任何运行在 JVM 中的类提供日志记录服务。因此我们可以利用这个框架来记录任何信息。
使用 JDK 中的 logger API,修改示例1的代码:
1 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 <%@page import="java.util.logging.Logger" %> 3 <html> 4 <head><title>Debug2</title></head> 5 <body> 6 7 <% 8 Logger logger = Logger.getLogger(this.getClass().getName()); 9 %> 10 11 <c:forEach var="counter" begin="1" end="10" step="1" > 12 <c:set var="myCount" value="${counter-5}" /> 13 <c:out value="${myCount}"/></br> 14 15 <% 16 String message = "counter=" 17 + pageContext.findAttribute("counter") 18 + " myCount=" 19 + pageContext.findAttribute("myCount"); 20 logger.info( message ); 21 %> 22 </c:forEach> 23 </body> 24 </html>
运行结果与示例1类似,但是它可以获得额外的信息输出至 stdout.log 文件中。在这我们使用了 logger 中的info方法。 stdout.log 内容如下:
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=1 myCount=-4
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=2 myCount=-3
24-Sep-2013 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter=3 myCount=-2
...
消息可以使用各种优先级发送,通过使用 sever(),warning(),info(),config(),fine(),finer(),finest() 方法。finest()方法用来记录最好的信息,而 sever()方法用来记录最严重的信息。
使用 Log4J 框架来将消息记录在不同的文件中,这些消息基于严重程度和重要性来进行分类。
3) 使用 JDB Debugger
可以在 JSP 和 servlets 中使用jdb命令来进行调试,就像调试普通的应用程序一样。
通常,我们直接调试 sun.servlet.http.HttpServer 对象来查看 HttpServer 在响应 HTTP 请求时执行 JSP/Servlets 的情况。这与调试 applets 非常相似。不同之处在于,applets 程序实际调试的是sun.applet.AppletViewer。
大部分调试器在调试 applets 时都能够自动忽略掉一些细节,因为它知道如何调试 applets。如果想要将调试对象转移到 JSP 身上,就需要做好以下两点:
(1) 设置调试器的classpath,让它能够找到 sun.servlet.http.HttpServer 和相关的类。
(2) 设置调试器的classpath,让它能够找到您的JSP文件和相关的类。
设置好 classpath 后,开始调试 sun.servlet.http.HttpServer 。您可以在JSP文件的任意地方设置断点,只要你喜欢,然后使用浏览器发送一个请求给服务器就应该可以看见程序停在了断点处。
3. JSP 国际化
国际化(i18n):表明一个页面根据访问者的语言或国家来呈现不同的翻译版本。
本地化(l10n):向网站添加资源,以使它适应不同的地区和文化。比如网站的印度语版本。
区域:这是一个特定的区域或文化,通常认为是一个语言标志和国家标志通过下划线连接起来。比如 "en_US" 代表美国英语地区。
JSP 容器能够根据 request 的 locale 属性来提供正确地页面版本。接下来给出了如何通过 request 对象来获得Locale 对象的语法:
java.util.Locale locale = request.getLocale()
1) 检测 Locale
下表列举出了Locale对象中比较重要的方法,用于检测request对象的地区,语言,和区域。所有这些方法都会在浏览器中显示国家名称和语言名称:
| 方法 | 描述 |
| String getCountry() | 返回国家/地区码的英文大写,或 ISO 3166 2-letter 格式的区域 |
| String getDisplayCountry() | 返回要显示给用户的国家名称 |
| String getLanguage() | 返回语言码的英文小写,或 ISO 639 格式的区域 |
| String getDisplayLanguage() | 返回要给用户看的语言名称 |
| String getISO3Country() | 返回国家名称的3字母缩写 |
| String getISO3Language() | 返回语言名称的3字母缩写 |
代码格式:
// Get locale
Locale locale = request.getLocale();
String language = locale.getLanguage();
String country = locale.getCountry();
2) 语言设置
JSP 可以使用西欧语言来输出一个页面,比如英语,西班牙语,德语,法语,意大利语等等。由此可见,设置 Content-Language 信息头来正确显示所有字符是很重要的。
第二点就是,需要使用 HTML 字符实体来显示特殊字符,比如 "ñ" 代表的是 ñ,"¡" 代表的是 ¡ :
// Set content type and language code.
response.setContentType("text/html");
response.setHeader("Content-Language", "jp");
String title = "問合せ内容"; // 日语
3) 区域特定日期
可以使用 java.text.DateFormat 类和它的静态方法 getDateTimeInstance() 来格式化日期和时间。接下来的这个例子显示了如何根据指定的区域来格式化日期和时间:
代码格式:
String date = DateFormat.getDateTimeInstance(
DateFormat.FULL,
DateFormat.SHORT,
locale).format(new Date());
4) 区域特定货币
可以使用 java.text.NumberFormat 类和它的静态方法 getCurrencyInstance() 来格式化数字。比如在区域特定货币中的 long 型和 double 型。接下来的例子显示了如何根据指定的区域来格式化货币:
代码格式:
Locale locale = request.getLocale( );
NumberFormat nft = NumberFormat.getCurrencyInstance(locale);
String formattedCurr = nft.format(1000000);
5) 区域特定百分比
可以使用 java.text.NumberFormat 类和它的静态方法 getPercentInstance() 来格式化百分比。
代码格式:
Locale locale = request.getLocale( );
NumberFormat nft = NumberFormat.getPercentInstance(locale);
String formattedPerc = nft.format(0.51);
示例
1 <%@ page contentType="text/html;charset=UTF-8" language="java"%> 2 <%@ page import="java.util.Locale,java.text.NumberFormat" %> 3 <%@ page import="java.text.DateFormat,java.util.Date" %> 4 <% 5 // Get locale 6 Locale locale = request.getLocale(); 7 String language = locale.getLanguage(); 8 String country = locale.getCountry(); 9 10 // Set content type and language code. 11 response.setContentType("text/html"); 12 response.setHeader("Content-Language", "jp"); 13 String title = "問合せ内容"; 14 15 // 16 String date = DateFormat.getDateTimeInstance( 17 DateFormat.FULL, 18 DateFormat.SHORT, 19 locale).format(new Date()); 20 21 // 22 NumberFormat nft = NumberFormat.getCurrencyInstance(locale); 23 String formattedCurr = nft.format(1000000); 24 25 // 26 NumberFormat nft2 = NumberFormat.getPercentInstance(locale); 27 String formattedPerc = nft2.format(0.51); 28 %> 29 <html> 30 <head> 31 <title>Locale</title> 32 </head> 33 <body> 34 <h1>Detecting Locale</h1> 35 <p> 36 <% 37 out.println("Language: " + language + "<br />"); 38 out.println("Country: " + country + "<br />"); 39 %> 40 </p> 41 <hr> 42 43 <h1><%=title%></h1> 44 <p>試用版を請求する</p> 45 <p>ミュニケーションとは</p> 46 <hr> 47 48 <h1>Locale Specific Dates</h1> 49 <p>Local Date: <%=date %></p> 50 <hr> 51 52 <h1>Locale Specific Currency</h1> 53 <p>Formatted Currency: <%=formattedCurr %></p> 54 <hr> 55 56 <h1>Locale Specific Percentage</h1> 57 <p>Formatted Percentage: <% out.print(formattedPerc); %></p> 58 59 </body> 60 </html>
输出
Detecting Locale
Language: zh
Country: CN
問合せ内容
試用版を請求する
ミュニケーションとは
Locale Specific Dates
Local Date: 2022年3月21日 星期一 上午10:35
Locale Specific Currency
Formatted Currency: ¥1,000,000.00
Locale Specific Percentage
Formatted Percentage: 51%
浙公网安备 33010602011771号