0%

最全的javaweb知识全集

最全的javaweb知识全集

servlet容器

在上面介绍servlet生命周期时,多次提到了servlet容器,其实在设计Servlet时,J2EE jdk只是提供了一个标准,在javax.servlet包以及子包下,而真正的实现是由servlet容器来进行实现的,如tomcat是在servlet-api.jar中实现的

servlet容器
1、可以创建servlet,并调用servlet的相关生命周期方法
2、JSP、Filter、Listener

下面将以tomcat作为servlet容器为例介绍web应用

web应用

WEB-INF

静态页面不要放在WEB-INF下,WEB-INF是给tomcat用的

WEB-INF 对于web应用的描述

  • web.xml 必须符合J2EE标准
  • lib 放jar包

tomcat配置项目位置

tomcat映射配置任意目录的项目
在conf下新建catalina文件夹,新建localhost文件夹,
在其中新建一个xml文件,文件名是url根路径
path当前没用 docBase为项目路径(编译之后的项目)

1
<Context path="" docBase="" reloadable="true">

web.xml配置servlet

load-on-startup参数指定servlet创建的时机 若为负数,则在第一次请求时被创建,若为0或者正数,在web应用被Servlet容器加载时创建实例,值越小越早被启动

init方法有入参 ServletConfig
配置ServletConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 注意servlet和servlet-mapping都是成对出现的 -->
<servlet>
<servlet-name>HW</servlet-name>
<servlet-class>com.zhanghe.study.servlet.HelloWorldServlet</servlet-class>
<!-- 配置servlet初始化init时中ServletConfig参数-->
<init-param>
<param-name>name</param-name>
<param-value>john</param-value>
</init-param>
<!-- servlet加载时机 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!-- 对应servlet标签中的servlet-name值 -->
<servlet-name>HW</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

​ 获取ServletConfig值

1
2
3
4
// 获取指定的属性
config.getInitParameter("name")
// 获取所有的属性
config.getInitParameters()

异常处理

当servlet出现异常时,servlet容器使用exception-type元素来找到与抛出的异常类型相匹配的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ExceptionHandler extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception");
Integer code = (Integer) req.getAttribute("javax.servlet.error.status_code");
String message = (String) req.getAttribute("javax.servlet.error.message");
System.out.println("=========");
System.out.println(throwable);
System.out.println("=========");
System.out.println(code);
System.out.println("=========");
System.out.println(message);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 配置异常处理的servlet -->
<servlet>
<servlet-name>ExceptionHandler</servlet-name>
<servlet-class>com.zhanghe.study.servlet.ExceptionHandler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ExceptionHandler</servlet-name>
<url-pattern>/ExceptionHandler</url-pattern>
</servlet-mapping>
<!-- 配置哪些错误码会调用该异常处理类 -->
<error-page>
<error-code>404</error-code>
<location>/ExceptionHandler</location>
</error-page>
<!-- 配置哪些异常类型会调用该异常处理类 -->
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/ExceptionHandler</location>
</error-page>

如果出现异常,会在请求域中设置相应的属性

可以使用request.getAttribute(“”)取出

1
2
3
4
5
6
javax.servlet.error.status_code //错误码,Integer类型
javax.servlet.error.exception_type // 异常类型,Class类型
javax.servlet.error.message //异常信息,String类型
javax.servlet.error.request_uri //出现异常的uri地址,String类型
javax.servlet.error.exception //异常,Throwable类型
javax.servlet.error.servlet_name //servlet名称,String类型

上传文件

1
2
3
4
5
6
<!-- 上传文件一定要使用post请求
enctype需要设置为multipart/form-data
input标签的type类型设为file
-->
<form method="post" enctype="multipart/form-data">
<input type="file" name="file">

form表单的编码格式
①application/x-www-form-urlencoded 默认 在发送前编码所有字符
②multipart/form-data 不对字符编码,二进制
③text/plain 空格转换为+号,但不对特殊字符编码

使用读取流的方式来读取太过于麻烦 request.getInputStream() 获取到的是整个请求体,需要解析各个字段和分隔
解析multipart/form-data比较复杂
可以使用外部依赖包
commons-fileupload.jar 依赖于 commons-io.jar

1
2
3
4
5
6
<!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>

commons-fileupload解析请求,解析成FileItem集合,无论是文本域还是文件域
使用FileItem.isFormField()来判断是不是一个表单域
表单域 item.getFieldName item.getString

​ 非表单域 item.getFieldName item.getName item.getContentType item.isImemory item.getSize item.getInputStream

国际化

  • 国际化(i18n): i18n internationalization,网站能够提供翻译成访问者的语言或国籍的不同版本的内容
  • 本地化(i10n): 向网站添加资源,使其适应特定的地理或文化区域,例如将网站翻译为中文
  • 区域设置:通常为语言符号后跟一个由下划线分隔的国家符号。例如”en_US”

获取区域

1
2
//获取当前国家和语言
Locale locale = request.getLocale();

获取区域设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 获取该区域设置的国家
public String getCountry() {
return baseLocale.getRegion();
}
// 获取该区域设置的国家名称
public final String getDisplayCountry() {
return getDisplayCountry(getDefault(Category.DISPLAY));
}
// 获取该区域设置的语言代码
public String getLanguage() {
return baseLocale.getLanguage();
}
// 获取该区域设置的语言名称
public final String getDisplayLanguage() {
return getDisplayLanguage(getDefault(Category.DISPLAY));
}
// 返回该区域设置的国家的三个字母缩写
public String getISO3Country() throws MissingResourceException {
String country3 = getISO3Code(baseLocale.getRegion(), LocaleISOData.isoCountryTable);
if (country3 == null) {
throw new MissingResourceException("Couldn't find 3-letter country code for "
+ baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
}
return country3;
}
// 返回该区域设置的语言的三个字母缩写
public String getISO3Language() throws MissingResourceException {
String lang = baseLocale.getLanguage();
if (lang.length() == 3) {
return lang;
}

String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
if (language3 == null) {
throw new MissingResourceException("Couldn't find 3-letter language code for "
+ lang, "FormatData_" + toString(), "ShortLanguage");
}
return language3;
}

时间国际化

时间格式化 DateFormat

货币国际化

数字、货币格式化 NumberFormat

字符串国际化

字符串格式化 MessageFormat

1
2
3
4
5
String str = "Date: {0},Salary: {1}";
Locale locale = Locale.CHINA;
Date date = new Date();
double sa1 = 12345.12;
MessageFormat.format(str,date,sa1);

国际化配置

native2ascii命令在jdk下 可以查看ascii码

1
2
Locale locale = Locale.CHINA;
ResourceBundle bundle = ResourceBundle.getBundle("i18n",locale);

在配置文件中i18n.properties i18n_en_US.properties i18n_zh_CN.properties
根据locale来找不同的配置文件

中文乱码问题
GET请求 ①tomcat的server.xml文件中,在Connector 节点中添加useBodyEncodingForURI=”true” 属性 使用请求体的编码,然后在获取请求内容之前使用request.setCharacterEncoding(“UTF-8”)
②tomcat的server.xml文件中,在Connector 节点中添加URIEncoding=”UTF-8”属性
③tomcat的get请求默认使用ISO-8859-1来编码,可以在获取的时候进行转码,new String(request.getParameter(“name”).getBytes(“ISO-8859-1”),”UTF-8”)

多个请求使用同一个Servlet
第一种方案:在url加上入参method
根据method进行分发

​ 第二种方案:
​ web.xml使用*.do来匹配Servlet
​ 根据 request.getServletPath()然后反射调用方法

表单的重复提交
重复提交的情况
①在表单提交到一个Servlet,Servlet又通过请求转发的方式响应了一个页面,此时地址栏还保留着Servlet的那个路径,在响应页面点击刷新
②在响应页面没有到达时重复点击提交按钮
③点击返回,再点击提交

不是重复提交的情况
①点击返回之后,刷新页面,再点击提交

如何避免表单的重复提交
使用session,生成属性,移除属性

HttpServletRequestWrapper类包装原始的request对象,实现了HttpServletRequest接口的所有方法,内部调用了所包装的
request对象的对应方法
相应的也有HttpServletResponseWrapper类来包装原始的response对象
继承HttpServletRequestWrapper,重写