Servlet
HttpServletRequest对象
HttpServletRequest对象代表客户端浏览器的请求,当客户端浏览器通过HTTP协议访问服务器时,HTTP请求中的所有信息都会被Tomcat所解析并封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
获取请求的信息
req.getRequestURL()返回客户端浏览器发出请求时的完整URL。
req.getRequestURI()返回请求行中指定资源部分。
req.getRemoteAddr()返回发出请求的客户机的IP地址。
req.getLocalAddr()返回WEB服务器的IP地址。
req.getLocalPort()返回WEB服务器处理Http协议的连接器所监听的端口。
packagecom.itbaizhan;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
importjava.io.PrintWriter;
publicclassGetRequestInfoServletextendsHttpServlet {
@Override
protectedvoiddoGet(HttpServletRequestreq, HttpServletResponseresp) throwsServletException, IOException {
//获取客户端浏览器发出请求时的完整的URL
StringURL=req.getRequestURL().toString();
//返回请求行中指定的资源部分
StringURI=req.getRequestURI();
//返回发出请求的客户机的IP地址
StringClientAddr=req.getRemoteAddr();
//返回WEB服务器的IP地址
StringServerAddr=req.getLocalAddr();
//返回WEB服务器处理http协议的连接器所监听的端口
intlocalPort=req.getLocalPort();
PrintWriterpw=resp.getWriter();
pw.println("URL:"+URL);
pw.println("URI:"+URI);
pw.println("ClientAddr:"+ClientAddr);
pw.println("ServerAddr:"+ServerAddr);
pw.println("Port:"+localPort);
pw.flush();
pw.close();
}
}
在web.xml中配置
<!-- 获取请求的信息-->
<servlet>
<servlet-name>getRequestInfoServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getRequestInfoServlet</servlet-name>
<url-pattern>/getRequestInfoServlet.do</url-pattern>
</servlet-mapping>
获取请求数据
获取表单数据
根据key获取指定value
req.getParameter("key");(表单里面任何值都是字符串类型)
根据key获取对应的value,返回一个字符串。String str = req.getParameter("key");
如何将静态的资源例如HTML页面放到web项目中??
在web的根目录下创建HTML页面
首先创建页面提交数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- action表单提交的地址 method提交的方式post-->
<form action="getRequestData.do" method="post">
<input type="text" name="username"> <br/>
<input type="password" name="passwd"> <br/>
<input type="submit" value="ok">
</form>
</body>
</html>
在创建servlet获取请求数据
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class GetRequestInfoServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取客户端浏览器发出请求时的完整的URL
String URL = req.getRequestURL().toString();
//返回请求行中指定的资源部分
String URI = req.getRequestURI();
//返回发出请求的客户机的IP地址
String ClientAddr = req.getRemoteAddr();
//返回WEB服务器的IP地址
String ServerAddr = req.getLocalAddr();
//返回WEB服务器处理http协议的连接器所监听的端口
int localPort = req.getLocalPort();
PrintWriter pw= resp.getWriter();
pw.println("URL:"+URL);
pw.println("URI:"+URI);
pw.println("ClientAddr:"+ClientAddr);
pw.println("ServerAddr:"+ServerAddr);
pw.println("Port:"+localPort);
pw.flush();
pw.close();
}
}
最后配置web.xml的相关的信息
<!-- 获取请求数据-->
<servlet>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestFormDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<!-- 这里的url-pattern中的值为form表单中action的值-->
<url-pattern>/getRequestData.do</url-pattern>
</servlet-mapping>
最后在浏览器的地址输入AddUser.html;就可以了
获取复选框(checkbox组件)中的值
req.getParameterValues("checkboxkey");获取复选框(checkbox组件)中的值,返回一个字符串数组。
String[] userlikes =req.getParameterValues("checkboxkey");
创建带有复选框的html页面
<!-- action表单提交的地址 method提交的方式post-->
<form action="getRequestData.do" method="post">
账号:<input type="text" name="username"> <br/>
密码:<input type="password" name="passwd"> <br/>
爱好:<input type="checkbox" name="userlike" value="Sport" />体育<br/>
<input type="checkbox" name="userlike" value="Sport" />音乐<br/>
<input type="checkbox" name="userlike" value="Sport" />羽毛球<br/>
<input type="checkbox" name="userlike" value="Sport" />乒乓球<br/>
<input type="submit" value="ok">
</form>
编写Servlet类
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
/**
* 获取请求数据
*/
public class GetRequestDataServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名 getParameter(key)里面的key就是input标签里面的name的值
String username = req.getParameter("username");
//获取用户的密码
String userpwd = req.getParameter("passwd");
//获取复选框的值
String [] userlikes=req.getParameterValues("userlike");
List<String> list = Arrays.asList(userlikes);
PrintWriter pw= resp.getWriter();
pw.println("username:"+username);
pw.println("userpasswd:"+userpwd);
pw.println("UserLikes:"+list);
pw.flush();
pw.close();
}
}
web.xml中的配置
<!-- 获取请求数据-->
<servlet>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<!-- 这里的url-pattern中的值为form表单中action的值-->
<url-pattern>/getRequestData.do</url-pattern>
</servlet-mapping>
获取所有提交数据的Key
req.getParameterNames()
获取请求中所有数据的key,该方法返回一个枚举类型。
Enumeration<String> parameterNames =req.getParameterNames();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- action表单提交的地址 method提交的方式post-->
<form action="getRequestData.do" method="post">
账号:<input type="text" name="username"> <br/>
密码:<input type="password" name="passwd"> <br/>
爱好:<input type="checkbox" name="userlike" value="Sport" />体育<br/>
<input type="checkbox" name="userlike" value="Sport" />音乐<br/>
<input type="checkbox" name="userlike" value="Sport" />羽毛球<br/>
<input type="checkbox" name="userlike" value="Sport" />乒乓球<br/>
<input type="submit" value="ok">
</form>
</body>
</html>
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
/**
* 获取请求数据
*/
public class GetRequestDataServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名 getParameter(key)里面的key就是input标签里面的name的值
String username = req.getParameter("username");
//获取用户的密码
String userpwd = req.getParameter("passwd");
//获取复选框的值
String [] userlikes=req.getParameterValues("userlike");
List<String> list = Arrays.asList(userlikes);
//获取表单中所有的name的值即所有的key
Enumeration<String> parameterNames = req.getParameterNames();
List<String> paraList =new ArrayList<>();
while (parameterNames.hasMoreElements()){
paraList.add(parameterNames.nextElement());
}
PrintWriter pw= resp.getWriter();
pw.println("username:"+username);
pw.println("userpasswd:"+userpwd);
pw.println("UserLikes:"+list);
pw.println("Name:"+paraList);
pw.flush();
pw.close();
}
}
<!-- 获取请求数据-->
<servlet>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<!-- 这里的url-pattern中的值为form表单中action的值-->
<url-pattern>/getRequestData.do</url-pattern>
</servlet-mapping>
最后结果
使用Map结构获取提交数据
req.getParameterMap()
获取请求中所有的数据并存放到一个Map结构中,该方法返回一个Map,其中key为String类型value为String[]类型。
Map<String, String[]> parameterMap =req.getParameterMap()
可以获取单选框或者复选框的值
编写的HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- action表单提交的地址 method提交的方式post-->
<form action="getRequestData.do" method="post">
账号:<input type="text" name="username"> <br/>
密码:<input type="password" name="passwd"> <br/>
爱好:<input type="checkbox" name="userlike" value="Sport" />体育<br/>
<input type="checkbox" name="userlike" value="Sport" />音乐<br/>
<input type="checkbox" name="userlike" value="Sport" />羽毛球<br/>
<input type="checkbox" name="userlike" value="Sport" />乒乓球<br/>
<input type="submit" value="ok">
</form>
</body>
</html>
编写的servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* 获取请求数据
*/
public class GetRequestDataServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名 getParameter(key)里面的key就是input标签里面的name的值
String username = req.getParameter("username");
//获取用户的密码
String userpwd = req.getParameter("passwd");
//获取复选框的值
String [] userlikes=req.getParameterValues("userlike");
List<String> list = Arrays.asList(userlikes);
//获取表单中所有的name的值即所有的key
Enumeration<String> parameterNames = req.getParameterNames();
List<String> paraList =new ArrayList<>();
while (parameterNames.hasMoreElements()){
paraList.add(parameterNames.nextElement());
}
//使用Map结构获取提交的表单的数据
Map<String, String[]> parameterMap = req.getParameterMap();
//遍历Map获取key和Value
Iterator<Map.Entry<String,String[]>> iterator =parameterMap.entrySet().iterator();
PrintWriter pw= resp.getWriter();
pw.println("username:"+username);
pw.println("userpasswd:"+userpwd);
pw.println("UserLikes:"+list);
pw.println("Name:"+paraList);
//遍历迭代器,获取表单中的所有的key和value
while (iterator.hasNext()){
Map.Entry<String,String[]> entry = iterator.next();
String key = entry.getKey();;
String value[] =entry.getValue();
pw.println(key+" = "+Arrays.asList(value));
}
pw.flush();
pw.close();
}
}
编写的web.xml
<!-- 获取请求数据-->
<servlet>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<!-- 这里的url-pattern中的值为form表单中action的值-->
<url-pattern>/getRequestData.do</url-pattern>
</servlet-mapping>
设置请求的编码
req.setCharacterEncoding("utf-8")
请求的数据包基于字节在网络上传输,Tomcat接收到请求的数据包后会将数据包中的字节转换为字符。在Tomcat中使用的是ISO-8859-1的单字节编码完成字节与字符的转换,所以数据中含有中文就会出现乱码,可以通过req.setCharacterEncoding("utf-8")方法来对提交的数据根据指定的编码方式重新做编码处理。
编写的HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- action表单提交的地址 method提交的方式post-->
<form action="getRequestData.do" method="post">
账号:<input type="text" name="username"> <br/>
密码:<input type="password" name="passwd"> <br/>
爱好:<input type="checkbox" name="userlike" value="Sport" />体育<br/>
<input type="checkbox" name="userlike" value="Sport" />音乐<br/>
<input type="checkbox" name="userlike" value="Sport" />羽毛球<br/>
<input type="checkbox" name="userlike" value="Sport" />乒乓球<br/>
<input type="submit" value="ok">
</form>
</body>
</html>
编写的servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* 获取请求数据
*/
public class GetRequestDataServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求的编码
req.setCharacterEncoding("utf-8");
//获取用户名 getParameter(key)里面的key就是input标签里面的name的值
String username = req.getParameter("username");
System.out.println(username);
//获取用户的密码
String userpwd = req.getParameter("passwd");
//获取复选框的值
String [] userlikes=req.getParameterValues("userlike");
List<String> list = Arrays.asList(userlikes);
//获取表单中所有的name的值即所有的key
Enumeration<String> parameterNames = req.getParameterNames();
List<String> paraList =new ArrayList<>();
while (parameterNames.hasMoreElements()){
paraList.add(parameterNames.nextElement());
}
//使用Map结构获取提交的表单的数据
Map<String, String[]> parameterMap = req.getParameterMap();
//遍历Map获取key和Value
Iterator<Map.Entry<String,String[]>> iterator =parameterMap.entrySet().iterator();
PrintWriter pw= resp.getWriter();
pw.println("username:"+username);
pw.println("userpasswd:"+userpwd);
pw.println("UserLikes:"+list);
pw.println("Name:"+paraList);
//遍历迭代器,获取表单中的所有的key和value
while (iterator.hasNext()){
Map.Entry<String,String[]> entry = iterator.next();
String key = entry.getKey();;
String value[] =entry.getValue();
pw.println(key+" = "+Arrays.asList(value));
}
pw.flush();
pw.close();
}
}
web.xml配置文件
<!-- 获取请求数据-->
<servlet>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetRequestFormDataServlet</servlet-name>
<!-- 这里的url-pattern中的值为form表单中action的值-->
<url-pattern>/getRequestData.do</url-pattern>
</servlet-mapping>
资源的访问的路径
绝对路径
绝对路径访问资源表示直接以”/”作为项目的Context Path。该方式适用于以”/”作为项目的Context Path。
相对路径
相对路径访问资源表示会相对于项目的Context Path作为相对路径。该方式适用于为项目指定的具体的Context Path。
获取请求头的信息
req.getHeader("headerKey")
根据请求头中的key获取对应的value。
编写servlet类
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 获取请求头部的信息
*/
public class GetRequestHeaderServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String headerInfo = req.getHeader("user-agent");
PrintWriter pw= resp.getWriter();
pw.println("user-agent:"+headerInfo);
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 获取请求头部的信息-->
<servlet>
<servlet-name>getRequestHeaderServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestHeaderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getRequestHeaderServlet</servlet-name>
<url-pattern>/getRequestHeaderServlet.do</url-pattern>
</servlet-mapping>
req.getHeaderNames()
获取请求头中所有的key,该方法返回枚举类型。
编写的servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
/**
* 获取请求头部的信息
*/
public class GetRequestHeaderServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求头中根据指定的key获取值
String headerInfo = req.getHeader("user-agent");
//获取请求头中所有的key,返回的是一个枚举类型
Enumeration<String> headerNames = req.getHeaderNames();
PrintWriter pw= resp.getWriter();
pw.println("user-agent:"+headerInfo);
while (headerNames.hasMoreElements()){
String key = headerNames.nextElement();
String value = req.getHeader(key);
pw.println(key+":"+value);
}
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 获取请求头部的信息-->
<servlet>
<servlet-name>getRequestHeaderServlet</servlet-name>
<servlet-class>com.itbaizhan.GetRequestHeaderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getRequestHeaderServlet</servlet-name>
<url-pattern>/getRequestHeaderServlet.do</url-pattern>
</servlet-mapping>
获取请求头的案例
需求:编写一个Servlet,如果浏览器的语言是zh-CN,显示“你好,聪明的中国人!”,如果浏览器的语言设置为en-US,那么则显示“Hello,American”。
编写serlvet程序
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 需求:编写一个Servlet,如果浏览器的语言是zh-CN,显示“你好,
* 聪明的中国人!”,如果浏览器的语言设置为en-US,那么则显示
* “Hello,American”。
*/
public class LanguageExampleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String language = req.getHeader("accept-language");
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw= resp.getWriter();
if (language.startsWith("zh-CN")){
pw.println("你好,聪明的中国人!!");
}else if (language.startsWith("en-US")){
pw.println("Hello,American");
}else {
pw.println("对不起,我不认识你!!");
}
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 获取请求头的案例-->
<servlet>
<servlet-name>LanguageExampleServlet</servlet-name>
<servlet-class>com.itbaizhan.LanguageExampleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LanguageExampleServlet</servlet-name>
<url-pattern>/LanguageExampleServlet.do</url-pattern>
</servlet-mapping>
HttpServletRequest对象的声明周期
当有请求到达Tomcat时,Tomcat会创建HttpServletRequest对象,并将该对象通过参数的方式传递到我们Servlet的方法中,当处理请求处理完毕并产生响应后该对象生命周期结束。
HttpServletResponse对象
HttpServletResponse对象代表服务器的响应。这个对象中封装了响应客户端浏览器的流对象,以及向客户端浏览器响应的响应头、响应数据、响应状态码等信息。
设置响应的类型
resp.setContentType("MIME")
该方法可通过MIME-Type设置响应类型。
设置字符的类型
常见的字符型响应类型:
resp.setContentType("text/html")设置响应类型为文本型,内容含有html字符串,是默认的响应类型
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 设置字符型响应
*/
public class ResponseCharacterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setContentType("text/plain");
PrintWriter pw= resp.getWriter();
pw.println("<!DOCTYPE html>");
pw.println("<html lang=en>");
pw.println("<head>");
pw.println("<meta charset=UTF-8>");
pw.println("<title>Document</title>");
pw.println("</head>");
pw.println("<body>");
pw.println("<font color=blue>HelloWorld</font>");
pw.println("</body>");
pw.println("</html>");
pw.flush();
pw.close();
}
}
显示的结果为:
resp.setContentType("text/plain")设置响应类型为文本型,内容是普通文本。
编写的servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 设置字符型响应
*/
public class ResponseCharacterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain");
PrintWriter pw= resp.getWriter();
pw.println("<!DOCTYPE html>");
pw.println("<html lang=en>");
pw.println("<head>");
pw.println("<meta charset=UTF-8>");
pw.println("<title>Document</title>");
pw.println("</head>");
pw.println("<body>");
pw.println("<font color=blue>HelloWorld</font>");
pw.println("</body>");
pw.println("</html>");
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 设置字符型响应-->
<servlet>
<servlet-name>responseCharacterServlet</servlet-name>
<servlet-class>com.itbaizhan.ResponseCharacterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>responseCharacterServlet</servlet-name>
<url-pattern>/responseCharacterServlet.do</url-pattern>
</servlet-mapping>
显示的结果:
resp.setContentType("application/json")设置响应类型为JSON格式的字符串。
设置字节型响应
常见的字节型响应:
resp.setContentType("image/jpeg")设置响应类型为图片类型,图片类型为jpeg或jpg格式。
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class ResponseByteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//给定读取响应图片的路径
File file=new File("d:/tcx.jpg");
//创建读取图片的IO流对象
InputStream is=new FileInputStream(file);
//图片缓冲区
byte [] buff=new byte[is.available()];
is.read(buff);
//设置响应的类型
resp.setContentType("image/jpeg");
//获取字节输出流对象
ServletOutputStream os = resp.getOutputStream();
os.write(buff);
os.flush();
os.close();
}
}
编写web.xml
<!-- 设置字节响应-->
<servlet>
<servlet-name>responseByteServlet</servlet-name>
<servlet-class>com.itbaizhan.ResponseByteServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>responseByteServlet</servlet-name>
<url-pattern>/responseByteServlet.do</url-pattern>
</servlet-mapping>
resp.setContentType("image/gif")设置响应类型为图片类型,图片类型为gif格式。
设置响应编码
设置响应编码的两种方式
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");不仅发送到浏览器的内容会使用UTF-8编码,而且还通知浏览器使用UTF-8编码方式进行显示。所以总能正常显示中文
案例:
在没有设置响应的编码之前的servlet显示为:
设置相应的编码之后:
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloWorld extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter pw = resp.getWriter();
pw.println("<!DOCTYPE html>");
pw.println("<html lang=en>");
pw.println("<head>");
pw.println("<meta charset=UTF-8>");
pw.println("<title>Document</title>");
pw.println("</head>");
pw.println("<body>");
pw.println("<font color=blue>百战程序员</font>");
pw.println("</body>");
pw.println("</html>");
pw.flush();
pw.close();
}
}
编写web.xml
<servlet>
<servlet-name>HWorldello</servlet-name>
<servlet-class>com.itbaizhan.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HWorldello</servlet-name>
<url-pattern>/helloworld.do</url-pattern>
</servlet-mapping>
response.setCharacterEncoding("utf-8");仅仅是发送的浏览器的内容是UTF-8编码的,至于浏览器是用哪种编码方式显示不管。 所以当浏览器的显示编码方式不是UTF-8的时候,就会看到乱码,需要手动指定浏览器编码。
在响应中添加附加的信息
重定向响应
response.sendRedirect(URL地址)
重定向响应会在响应头中添加一个Location的key对应的value是给定的URL。客户端浏览器在解析响应头后自动向Location中的URL发送请求。
重定向响应的特点
重定向会产生两次请求两次响应。重定向的URL是由客户端浏览器发送的。浏览器地址栏会有变化。
案例:
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("https://blog.csdn.net/");
}
}
编写web.xml
<!-- 重定向响应-->
<servlet>
<servlet-name>redirectServlet</servlet-name>
<servlet-class>com.itbaizhan.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>redirectServlet</servlet-name>
<url-pattern>/redirectServlet.do</url-pattern>
</servlet-mapping>
重定向响应的案例
需求:创建一个搜索页面,通过百度搜索引擎完成内容搜索。
编写HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="redirectServlet.do" method="post">
搜索:<input type="text" name="search" />
<input type="submit" value="OK" />
</form>
</body>
</html>
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应编码
resp.setCharacterEncoding("utf-8");
//获取用户数据
String search = req.getParameter("search");
resp.sendRedirect("https://www.baidu.com/s?wd="+ URLEncoder.encode(search,"utf-8"));
}
}
编写web.xml
<!-- 重定向响应-->
<servlet>
<servlet-name>redirectServlet</servlet-name>
<servlet-class>com.itbaizhan.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>redirectServlet</servlet-name>
<url-pattern>/redirectServlet.do</url-pattern>
</servlet-mapping>
文件的下载
在实现文件下载时,我们需要在响应头中添加附加信息。
response.addHeader("Content-Disposition","attachment; filename="+文件名);
Content-Disposition:attachment
该附加信息表示作为对下载文件的一个标识字段。不会在浏览器中显示而是直接做下载理。
filename=文件名表示指定下载文件的文件名。
解决文件名中文乱码问题:resp.addHeader("Content-Disposition","attachment;filename="+newString(file.getName().getBytes("gbk"),"iso-8859-1"));
实际操作:
编写servlet类
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class DownLoadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File file =new File("d:/tcx.jpg");
InputStream is=new FileInputStream(file);
byte [] buff =new byte[is.available()];
is.read(buff);
//在响应中添加附加的信息
resp.addHeader("Content-Disposition","attachment;filename"+ file.getName());
//产生响应
OutputStream os = resp.getOutputStream();
os.write(buff);
os.flush();
os.close();
}
}
编写web.xml
<!-- 文件的下载-->
<servlet>
<servlet-name>downLoadServlet</servlet-name>
<servlet-class>com.itbaizhan.DownLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>downLoadServlet</servlet-name>
<url-pattern>/downLoadServlet.do</url-pattern>
</servlet-mapping>
解决文件名中文乱码的问题
resp.addHeader("Content-Disposition","attachment;filename="+newString(file.getName().getBytes("gbk"),"iso-8859-1"));
修改servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class DownLoadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File file =new File("d:/田春旭.jpg");
System.out.println(file.getName());
InputStream is=new FileInputStream(file);
byte [] buff =new byte[is.available()];
is.read(buff);
//在响应中添加附加的信息
resp.addHeader("Content-Disposition","attachment;filename"+ new String(file.getName().getBytes("gbk"),"iso8859-1"));
//产生响应
OutputStream os = resp.getOutputStream();
os.write(buff);
os.flush();
os.close();
}
}
ServletContext对象
ServletContext介绍
ServletContext官方叫Servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象。这个对象全局唯一,而且Web应用中的所有Servlet都共享这个对象。所以叫全局应用程序共享对象。
ServletContext对象的作用
相对路径转绝对路径 获取容器的附加信息 读取配置信息 全局容器
ServletContext对象的使用
相对路径转绝对路径
context.getRealPath("path")该方法可以将一个相对路径转换为绝对路径,在文件上传与下载时需要用到该方法做路径的转换。
绝对路径会产生问题,就是不能够跨平台,在其他的平台上面就没有d盘的概念
可以在项目中创建目录结构,在项目中的目录结构是不会改变的。将静态的资源,例如图片等内容放到项目的根目录下,或者根目录的子目录中。相对目录的相对点,永远是项目的根作为相对点。
利用servletContxt对象进行创建
案例:修改的servlet
package com.itbaizhan;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class DownLoadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletContext对象,这个方法是servlet继承到的
ServletContext servletContext = this.getServletContext();
//路径的转换
String realPath = servletContext.getRealPath("image/田春旭.jpg");
System.out.println(realPath);
File file =new File(realPath);
System.out.println(file.getName());
InputStream is=new FileInputStream(file);
byte [] buff =new byte[is.available()];
is.read(buff);
//在响应中添加附加的信息
resp.addHeader("Content-Disposition","attachment;filename"+ new String(file.getName().getBytes("gbk"),"iso8859-1"));
//产生响应
OutputStream os = resp.getOutputStream();
os.write(buff);
os.flush();
os.close();
}
}
编写web.xml
<!-- 文件的下载-->
<servlet>
<servlet-name>downLoadServlet</servlet-name>
<servlet-class>com.itbaizhan.DownLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>downLoadServlet</servlet-name>
<url-pattern>/downLoadServlet.do</url-pattern>
</servlet-mapping>
获取容器的附加信息
servletContext.getServerInfo()返回Servlet容器的名称和版本号
servletContext.getMajorVersion()
返回Servlet容器所支持Servlet的主版本号。
servletContext.getMinorVersion()返回Servlet容器所支持Servlet的副版本号。
编写servlet类
package com.itbaizhan;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class GetBaseInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//获取servlet容器的名称和版本号
String serverInfo = servletContext.getServerInfo();
//返回servlet做支持的主版本号
int majorVersion = servletContext.getMajorVersion();
//返回servlet容器所支持servlet的副版本号
int minorVersion = servletContext.getMinorVersion();
PrintWriter pw= resp.getWriter();
pw.println("serverInfo"+serverInfo);
pw.println("majorVersion"+majorVersion);
pw.println("minorVersion"+minorVersion);
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 获取容器的附加的信息-->
<servlet>
<servlet-name>getBaseInfoServlet</servlet-name>
<servlet-class>com.itbaizhan.GetBaseInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getBaseInfoServlet</servlet-name>
<url-pattern>/getBaseInfoServlet.do</url-pattern>
</servlet-mapping>
显示的结果
获取web.xml中的信息
<context-param>
<param-name>key</param-name>
<param-value>value</param-value>
</context-param>
servletContext.getInitParameter("key")该方法可以读取web.xml文件中标签中的配置信息。servletContext.getInitParameterNames()该方法可以读取web.xml文件中所有param-name标签中的值。
编写servlet
package com.itbaizhan;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class ContextInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//获取所有的<param-name>的值
Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
PrintWriter pw= resp.getWriter();
while (initParameterNames.hasMoreElements()){
String name = initParameterNames.nextElement();
String value = getInitParameter(name);
pw.println("Name:"+name+" = value:"+value);
}
pw.flush();
pw.close();
}
}
<!-- 获取web.xml的信息-->
<servlet>
<servlet-name>contextInfoServlet</servlet-name>
<servlet-class>com.itbaizhan.ContextInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>contextInfoServlet</servlet-name>
<url-pattern>/contextInfoServlet.do</url-pattern>
</servlet-mapping>
全局容器
servletContext.setAttribute("key",ObjectValue)
向全局容器中存放数据。
servletContext.getAttribute("key")从全局容器中获取数据。
servletContext.removeAttribute("key")根据key删除全局容器中的value。
编写servlet
package com.itbaizhan;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class GlobalContainerServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 获取全局容器的数据
*/
ServletContext servletContext = this.getServletContext();
String key1 = (String)servletContext.getAttribute("key1");
String key2 = (String)servletContext.getAttribute("key2");
PrintWriter pw= resp.getWriter();
pw.println("key1"+key1);
pw.println("key2"+key2);
pw.flush();
pw.close();
}
/**
* 向全局容器里面存放数据
* @throws ServletException
*/
@Override
public void init() throws ServletException {
ServletContext servletContext = this.getServletContext();
//向全局容器中存放数据
servletContext.setAttribute("key1","TCX");
servletContext.setAttribute("key2","ASD");
}
}
编写web.xml
<!-- 全局容器-->
<servlet>
<servlet-name>GlobalContainerServlet</servlet-name>
<servlet-class>com.itbaizhan.GlobalContainerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GlobalContainerServlet</servlet-name>
<url-pattern>/GlobalContainerServlet.do</url-pattern>
</servlet-mapping>
ServletContext对象的声明周期
当容器启动时会创建ServletContext对象并一直缓存该对象,直到容器关闭后该对象生命周期结束。ServletContext对象的生命周期非常长,所以在使用全局容器时不建议存放业务数据。
servletConfig对象
ServletConfig对象对应web.xml文件中的节点。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中。我们可以通过该对象读取节点中的配置信息
servletConfig.getInitParameter("key")该方法可以读取web.xml文件中标签中标签中的配置信息。
servletConfig.getInitParameterNames()该方法可以读取web.xml文件中当前标签中所有标签中的值。
编写servlet
package com.itbaizhan;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
/**
*获取ConfigServlet的信息
*/
public class GetConfigServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
PrintWriter pw= resp.getWriter();
//获取配置信息
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
String name = initParameterNames.nextElement();
String value = servletConfig.getInitParameter(name);
pw.println("key:"+name+" value:"+value);
}
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 获取ServletConfig的配置信息-->
<servlet>
<servlet-name>GetConfigServlet</servlet-name>
<servlet-class>com.itbaizhan.GetConfigServlet</servlet-class>
<init-param>
<param-name>key1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>key2</param-name>
<param-value>value2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>GetConfigServlet</servlet-name>
<url-pattern>/GetConfigServlet.do</url-pattern>
</servlet-mapping>
Cookie对象和httpSession对象
Cookie对象与HttpSession对象的作用是维护客户端浏览器与服务端的会话状态的两个对象。由于HTTP协议是一个无状态的协议,所以服务端并不会记录当前客户端浏览器的访问状态,但是在有些时候我们是需要服务端能够记录客户端浏览器的访问状态的,如获取当前客户端浏览器的访问服务端的次数时就需要会话状态的维持。在Servlet中提供了Cookie对象与HttpSession对象用于维护客户端与服务端的会话状态的维持。二者不同的是Cookie是通过客户端浏览器实现会话的维持,而HttpSession是通过服务端来实现会话状态的维持。
Cookie对象的特点
Cookie使用字符串存储数据
Cookie使用Key与Value结构存储数据
单个Cookie存储数据大小限制在4097个字节
Cookie存储的数据中不支持中文,Servlet4.0中支持
Cookie是与域名绑定所以不支持跨一级域名访问
Cookie对象保存在客户端浏览器内存或系统磁盘中
Cookie分为持久化Cooke与状态Cookie
浏览器在保存同一域名所返回Cookie的数量是有限的。不同浏览器支持的数量不同,Chrome浏览器为50个
浏览器每次请求时都会把与当前访问的域名相关的Cookie在请求中提交到服务端。
Cookie对象的创建
Cookie cookie = new Cookie("key","value")通过new关键字创建Cookie对象
response.addCookie(cookie)通过HttpServletResponse对象将Cookie写回给客户端浏览器。
创建servlet
package com.itbaizhan;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
/**
*获取ConfigServlet的信息
*/
public class GetConfigServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
PrintWriter pw= resp.getWriter();
//获取配置信息
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
String name = initParameterNames.nextElement();
String value = servletConfig.getInitParameter(name);
pw.println("key:"+name+" value:"+value);
}
pw.flush();
pw.close();
}
}
创建web.xml
<!-- 创建Cookie-->
<servlet>
<servlet-name>createCookie</servlet-name>
<servlet-class>com.itbaizhan.CreateCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>createCookie</servlet-name>
<url-pattern>/createCookie.do</url-pattern>
</servlet-mapping>
显示的结果
获取Cookie当中的数据
浏览器每次请求时都会把与当前访问的域名相关的Cookie在请求中提交到服务端。通过HttpServletRequest对象获取Cookie,返回Cookie数组。
Cookie[] cookies = request.getCookies()
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 获取Cookie数据
*/
public class GetCookieDataServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie [] cookies= req.getCookies();
//获取Cookie中的数据
PrintWriter pw= resp.getWriter();
for (int i = 0; i < cookies.length; i++) {
Cookie cookie= cookies[i];
String name = cookie.getName();
String value = cookie.getValue();
pw.println(name+" "+value);
}
pw.flush();
pw.close();
}
}
编写web.xml
<!-- 获取Cookie的数据-->
<servlet>
<servlet-name>GetCookieDataServlet</servlet-name>
<servlet-class>com.itbaizhan.GetCookieDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetCookieDataServlet</servlet-name>
<url-pattern>/GetCookieDataServlet.do</url-pattern>
</servlet-mapping>
显示的结果:
解决Cookie不支持中文
在Cookie中name的值不能使用中文,Value是可以的。但是在Servlet4.0版本之前Cookie中的Value也是不支持中文存储的,如果存储的数据中含有中文,代码会直接出现异常。我们可以通过对含有中文的数据重新进行编码来解决该问题。在Servlet4.0中的Cookie的Value开始支持中文存储。
java.lang.IllegalArgumentException: Control character in cookie value or attribute.
URLEncoder.encode("content","code")将内容按照指定的编码方式做URL编码处理。
URLDecoder.decode("content","code")将内容按照指定的编码方式做URL解码处理。
编写的servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
public class CreateCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建Cookie,通过new关键字进行创建
Cookie cookie=new Cookie(URLEncoder.encode("田春旭","utf-8"),"武汉");
resp.addCookie(cookie);
PrintWriter pw= resp.getWriter();
pw.println("Create Cookie is OK");
pw.flush();
pw.close();
}
}
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
/**
* 获取Cookie数据
*/
public class GetCookieDataServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie [] cookies= req.getCookies();
resp.setContentType("text/plain;charset=utf-8");
//获取Cookie中的数据
PrintWriter pw= resp.getWriter();
for (int i = 0; i < cookies.length; i++) {
Cookie cookie= cookies[i];
String name = cookie.getName();
String value = cookie.getValue();
pw.println(URLDecoder.decode(name,"utf-8") +" "+value);
}
pw.flush();
pw.close();
}
}
在编码后,获取的时候就要进行解码
cookie跨域的问题
域名分类:域名分为顶级域、顶级域名(一级域名)、二级域名。
域名等级的区别:一级域名比二级域名更高级,二级域名是依附于一级域名之下的附属分区域名,即二级域名是一级域名的细化分级。例如:baidu.com 为一级域名,news.baidu.com为二级域名。
状态cookie和持久化cookie
状态Cookie:Cookie对象仅会被缓存在浏览器所在的内存中。当浏览器关闭后Cookie对象 也会被销毁。
持久化Cookie:浏览器会对Cookie做持久化处理,基于文件形式保存在系统的指定目录中。在Windows10系统中为了安全问题不会显示Cookie中的内容。当Cookie对象创建后默认为状态Cookie。可以使用Cookie对象下的cookie.setMaxAge(60)方法设置失效时间,单位为秒。一旦设置了失效时间,那么该Cookie为持久化Cookie,浏览器会将Cookie对象持久化到磁盘中。当失效时间到达后文件删除。
Cookie的案例
要求:需求:当客户端浏览器第一次访问Servlet时响应“您好,欢迎您第一次访问!”,第二次访问时响应“欢迎您回来!”。
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 需求:当客户端浏览器第一次访问Servlet时响应“您好,欢迎您第一
* 次访问!”,第二次访问时响应“欢迎您回来!”。
*/
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie [] cookies= req.getCookies();
boolean flag =false;
if (cookies !=null){
for (Cookie cookie:cookies){
if ("welcome".equals(cookie.getName())){
flag = true;
break;
}
}
}
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw= resp.getWriter();
if (flag){
pw.println("欢迎您回来");
}else {
pw.println("您好,欢迎您第一次访问");
Cookie cookie=new Cookie("welcome","welcome");
cookie.setMaxAge(60);
resp.addCookie(cookie);
}
}
}
编写web.xml
<!-- Cookie的案例-->
<servlet>
<servlet-name>WelcomeServlet</servlet-name>
<servlet-class>com.itbaizhan.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WelcomeServlet</servlet-name>
<url-pattern>/WelcomeServlet.do</url-pattern>
</servlet-mapping>
Cookie总结
Cookie对于存储内容是基于明文的方式存储的,所以安全性很低。不要在Cookie中存放敏感数据。在数据存储时,虽然在Servlet4.0中Cookie支持中文,但是建议对Cookie中存放的内容做编码处理,也可提高安全性
HttpSession对象的特点
HttpSession保存在服务端HttpSession使用Key与Value结构存储数据HttpSession的Key是字符串类型,Value则是Object类型HttpSession存储数据大小无限制
HttpSession对象的创建
HttpSession对象的创建是通过request.getSession()方法来创建的。客户端浏览器在请求服务端资源时,如果在请求中没有jsessionid,getSession()方法将会为这个客户端浏览器创建一个新的HttpSession对象,并为这个HttpSession对象生成一个jsessionid,在响应中通过状态Cookie写回给客户端浏览器,如果在请求中包含了jsessionid,getSession()方法则根据这个ID返回与这个客户端浏览器对应的HttpSession对象。getSession()方法还有一个重载方法getSession(true|false)。当参数为true时与getSession()方法作用相同。当参数为false时则只去根据jsessionid查找是否有与这个客户端浏览器对应的HttpSession,如果有则返回,如果没有jsessionid则不会创建新的HttpSession对象。
HttpSession对象的使用
session.setAttribute("key",value)将数据存储到HttpSession对象中
Object value = session.getAttribute("key")根据key获取HttpSession中的数据,返回Object
Enumeration <String>attributeNames = session.getAttributeNames()获取HttpSession中所有的key,返回枚举类型
session.removeAttribute("key")根据key删除HttpSession中的数据
String id = session.getId()
根据获取当前HttpSession的SessionID,返回字符串类型
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class CreateHttpSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
//存放数据
session.setAttribute("key","ITBZ");
//获取sessionID
String sessionID=session.getId();
System.out.println(session);
PrintWriter pw= resp.getWriter();
pw.println("Create HttpSession is OK" +sessionID);
pw.flush();
pw.close();
}
}
HttpSession的销毁方式
HttpSession的销毁方式有两种:1、通过web.xml文件指定超时时间2、通过HttpSession对象中的invalidate()方法销毁当前HttpSession对象
我们可以在web.xml文件中指定HttpSession的超时时间,当到达指定的超时时间后,容器就会销该HttpSession对象,单位为分钟。该时间对整个web项目中的所有HttpSession对象有效。时间的计算方式是根据最后一次请求时间作为起始时间。只要用户继续访问,服务器就会更新HttpSession的最后访问时间,并维护该HttpSession。用户每访问服务器一次,无论是否读写HttpSession,服务器都认为该用户的HttpSession"活跃(active)"了一次,销毁时间则会重新计算。如果有哪个客户端浏览器对应的HttpSession的失效时间已到,那么与该客户端浏览器对应的HttpSession对象就会被销毁。其他客户端浏览器对应的HttpSession对象会继续保存不会被销毁。
创建HttpSession对象
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class CreateHttpSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求头
String header = req.getHeader("user-agent");
HttpSession session = req.getSession();
if (header.indexOf("Chrome") !=-1){
session.setAttribute("key","Chrome");
}else {
session.setAttribute("key","IE");
}
//存放数据
// session.setAttribute("key","ITBZ");
//获取sessionID
String sessionID=session.getId();
System.out.println(session);
PrintWriter pw= resp.getWriter();
pw.println("Create HttpSession is OK" +sessionID);
pw.flush();
pw.close();
}
}
获取httpsession对象
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class GetHttpSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建HttpSession对象
HttpSession session = req.getSession();
//根据key获取HttpSession中的数据。返回Object
String value =(String) session.getAttribute("key");
PrintWriter pw= resp.getWriter();
pw.println("value:"+value);
pw.flush();
pw.close();
}
}
在web.xml中配置超时的时间
<!-- 配置超时的时间-->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
我们也可以在Tomcat的web.xml文件中配置HttpSession的销毁时间。如果在Tomcat的web.xml文件中配置了HttpSession的超时时间对应的是Tomcat中所有的Web项目都有效。相当于配置了全局的HttpSession超时时间。如果我们在Web项目中配置了超时时间,那么会以Web项目中的超时时间为准。
invalidate()方法是HttpSession对象中所提供的用于销毁当前HttpSession的方法。我们通过调用该方法可以销毁当前HttpSession对象。
HttpSession的生命周期
在HttpSession对象生命周期中没有固定的创建时间与销毁时间。何时创建取决于我们什么时候第一次调用了getSession()或getSession(true)的方法。HttpSession对象的销毁时间取决于超时时间的到达以及调用了invalidate()方法。如果没有超时或者没有调用invalidate()方法,那么HttpSession会一直存储。默认超时时间为30分钟(Tomcat的web.xml文件配置的时间就是默认超时时间)。
HttpSession对象的总结
HttpSession与Cookie的区别:
1、cookie数据存放在客户的浏览器或系统的文件中,而HttpSession中的数据存放在服务器中。cookie不安全,而HttSession是安全的。2、单个cookie保存的数据不能超过4K,很多浏览器都限制一个域名保存cookie的数量。而HttpSession没有容量以及数量的限制。
HttpSession对象的使用建议
HttpSession对象是保存在服务端的,所以安全性较高。我们可以在HttpSession对象中存储数据,但是由于HttpSession对象的生命周期不固定,所以不建议存放业务数据。一般情况下我们只是存放用户登录信息。
自启动Servlet
自启动Servlet特点自动启动Servlet表示在Tomcat启动时就会实例化这个Servlet,他的实例化过程不依赖于请求,而是依赖容器的启动。可以通过在web.xml中的标签中通过1配置自启动Servlet
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class AutoStartServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter pw= resp.getWriter();
pw.println("AutoServlet............");
pw.flush();
pw.close();
}
@Override
public void init() throws ServletException {
System.out.println("AutoStartServlet init.............");
}
}
<!-- 自启动Servlet-->
<servlet>
<servlet-name>AutoStartServlet</servlet-name>
<servlet-class>com.itbaizhan.AutoStartServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AutoStartServlet</servlet-name>
<url-pattern>/AutoStartServlet.do</url-pattern>
</servlet-mapping>
通过自启动Servlet实现配置信息的读取
需求:修改文件下载案例,通过自启动Servlet读取配置信息。
编写servlet
package com.itbaizhan;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class AutoStartServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter pw= resp.getWriter();
pw.println("AutoServlet............");
pw.flush();
pw.close();
}
@Override
public void init() throws ServletException {
ServletConfig servletConfig = this.getServletConfig();
//获取servlet标签中的配置信息
String value = servletConfig.getInitParameter("path");
//获取全局容器对象
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("path",value);
System.out.println("AutoStartServlet init.............");
}
}
package com.itbaizhan;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class DownLoadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletContext对象,这个方法是servlet继承到的
ServletContext servletContext = this.getServletContext();
//获取存放图片路径的名字的名称
String value = (String) servletContext.getAttribute("path");
System.out.println(value);
//路径的转换
String realPath = servletContext.getRealPath(value+"/田春旭.jpg");
System.out.println(realPath);//D:\JAVAtomcat\apache-tomcat-9.0.34\webapps\servletdemo\image\田春旭.jpg
File file =new File(realPath);
System.out.println(file.getName());
InputStream is=new FileInputStream(file);
byte [] buff =new byte[is.available()];
is.read(buff);
//在响应中添加附加的信息
resp.addHeader("Content-Disposition","attachment;filename"+ new String(file.getName().getBytes("gbk"),"iso8859-1"));
//产生响应
OutputStream os = resp.getOutputStream();
os.write(buff);
os.flush();
os.close();
}
}
<!-- 文件的下载-->
<servlet>
<servlet-name>downLoadServlet</servlet-name>
<servlet-class>com.itbaizhan.DownLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>downLoadServlet</servlet-name>
<url-pattern>/downLoadServlet.do</url-pattern>
</servlet-mapping>
<!-- 自启动Servlet-->
<servlet>
<servlet-name>AutoStartServlet</servlet-name>
<servlet-class>com.itbaizhan.AutoStartServlet</servlet-class>
<init-param>
<param-name>path</param-name>
<param-value>image</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AutoStartServlet</servlet-name>
<url-pattern>/AutoStartServlet.do</url-pattern>
</servlet-mapping>
Servlet线程安全问题
在Servlet中使用的是多线程方式来执行service()方法处理请求,所以我们在使用Servlet时需要考虑到线程安全问题,在多线程中对于对象中的成员变量是最不安全的,所以不要在Servlet中通过成员变量的方式来存放数据,如果一定要使用成员变量存储数据,在对数据进行操作时需要使用线程同步的方式来解决线程安全问题,避免出现数据张冠李戴现象。
Servlet的url-pattern配置URL
URL的匹配规则
精确匹配
精确匹配是指中配置的值必须与url完全精确匹配。
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/demo.do</url-pattern>
</servlet-mapping>
http://localhost:8888/demo/demo.do 匹配http://localhost:8888/demo/suibian/demo.do 不匹配
扩展名匹配
在允许使用统配符作为匹配规则,“*”表示匹配任意字符。在扩展名匹配中只要扩展名相同都会被匹配和路径无关。注意,在使用扩展名匹配时在中不能使用“/”,否则容器启动就会抛出异常。
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
http://localhost:8888/demo/abc.do 匹配http://localhost:8888/demo/suibian/haha.do 匹配http://localhost:8888/demo/abc 不匹配
路径匹配
根据请求路径进行匹配,在请求中只要包含该路径都匹配。“*”表示任意路径以及子路径。
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/suibian/*</url-pattern>
</servlet-mapping>
http://localhost:8888/demo/suibian/haha.do 匹配http://localhost:8888/demo/suibian/hehe/haha.do 匹配http://localhost:8888/demo/hehe/heihei.do 不匹配
任意匹配
匹配“/”。匹配所有但不包含JSP页面。
<url-pattern>/AutoStartServlet.do</url-pattern>
http://localhost:8888/demo/suibian.do 匹配
http://localhost:8888/demo/addUser.html 匹配http://localhost:8888/demo/css/view.css 匹配http://localhost:8888/demo/addUser.jsp 不匹配http://localhost:8888/demo/user/addUser.jsp 不匹配
匹配所有
<url-pattern>/*</url-pattern>
http://localhost:8888/demo/suibian.do 匹配http://localhost:8888/demo/addUser.html 匹配http://localhost:8888/demo/suibian/suibian.do 匹配
优先顺序
当一个url与多个Servlet的匹配规则可以匹配时,则按照 “ 精确路径
最长路径 > 扩展名”这样的优先级匹配到对应的Servlet。
Servlet的多URL映射方式
在web.xml文件中支持将多个URL映射到一个Servlet中,但是相同的URL不能同时映射到两个Servlet中。
方式一
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/suibian/*</url-pattern>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
方式二
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/suibian/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
基于注解式开发Servlet
在Servlet3.0以及之后的版本中支持注解式开发Servlet。对于Servlet的配置不在依赖于web.xml配置文件,而是使用@WebServlet注解完成Servlet的配置。
@WebServlet
编写servlet
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 基于注解式开发
*/
//@WebServlet(urlPatterns = {"*.do","/suibian/*"}) 多url的映射
@WebServlet(urlPatterns = "/ann.do")
public class AnnotationServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter pw= resp.getWriter();
pw.println(":Annotation Servlet");
pw.flush();
pw.close();
}
}
@WebInitParam
编写的Servlet
package com.itbaizhan;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 配置初始化的参数
*/
@WebServlet(urlPatterns = "/initParam.do",initParams = {@WebInitParam(name = "key",value = "BJSXT"),@WebInitParam(name = "key2",value = "ITBZ")},loadOnStartup = 1)
public class InitParamServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
public void init() throws ServletException {
//获取servletConfig对象
ServletConfig servletConfig = this.getServletConfig();
String value1 =servletConfig.getInitParameter("key");
String value2 = servletConfig.getInitParameter("key2");
System.out.println(value1);
System.out.println(value2);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
String value1 =servletConfig.getInitParameter("key");
String value2 = servletConfig.getInitParameter("key2");
PrintWriter pw= resp.getWriter();
pw.println(value1);
pw.println(value2);
pw.flush();
pw.close();
}
}
文件上传
在Servlet3.0之前的版本中如果实现文件上传需要依赖apache的Fileupload组件,在Servlet3.0以及之后的版本中提供了Part对象处理文件上传,所以不在需要额外的添加Fileupload组件。在Servlet3.0以及之后的版本中实现文件上传时必须要在Servlet中开启多参数配置:
web.xml
Part对象中常用的方法
long getSize()上传文件的大小String getSubmittedFileName()上传文件的原始文件名String getName()获取<input name="upload" ...>标签中name属性值
InputStream getInputStream()获取上传文件的输入流void write(String path)保存文件至服务器
首先创建文件上传的页面
Filter过滤器
过滤器的作用
Filter过滤器是Servlet2.3中所提供的一个过滤请求与响应的对象。Filter过滤器既可以对客户端向服务器端发送的请求进行过滤,也可以对服务器端向客户端产生的响应进行过滤处理。
Filter对象的创建
创建一个Class实现Filter接口,并实现接口中三个抽象方法。init()方法:初始化方法,在创建Filter后立即调用。可用于完成初始化动作。doFilter()方法:拦截请求与响应方法,可用于对请求和响应实现预处理。destroy()方法:销毁方法,在销毁Filter之前自动调用。可用于完成资源释放等动作。
编写一个class
package com.itbaizhan;
import javax.servlet.*;
import java.io.IOException;
/**
*
* 第一个Filter的案例
*/
public class FirstFilter implements Filter {
/**
* 当Filter对象被实例化后被立即调用的方法
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init........");
}
/**
* 过滤请求和响应,当客户端浏览器请求的URL与Filter所定义的URL-patter所匹配那么该请求会进入到该方法进行过滤
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 对请求做处理
System.out.println("请求被过滤");
//对请求做放行的处理
filterChain.doFilter(servletRequest, servletResponse);
//对响应进行处理
System.out.println("响应被过滤");
}
/**
* 当Filter对象被销毁的时候会调用该方法
*/
@Override
public void destroy() {
Filter.super.destroy();
}
}
编写web.xml
<!-- 配置filter-->
<filter>
<filter-name>firstNmae</filter-name>
<filter-class>com.itbaizhan.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>firstNmae</filter-name>
<url-pattern>/getBaseInfoServlet.do</url-pattern>
</filter-mapping>
在Filter中设置请求的编码
需求:在Filter中实现对请求的编码的设置。
编写servlet过滤请求的编码
package com.itbaizhan;
import javax.servlet.*;
import java.io.IOException;
/**
* 设置请求编码的过滤器
*/
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置请求的编码
servletRequest.setCharacterEncoding("utf-8");
//不建议设置响应的编码,因为业务的类型不确定
//设置响应的编码
// servletResponse.setCharacterEncoding("utf-8");
//对请求做放行的处理
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
编写web.xml
<!-- 过滤请求的编码filter-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.itbaizhan.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
设置了请求的编码,那么servlet中便可以不在设置
package com.itbaizhan;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* 获取请求数据
*/
public class GetRequestDataServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求的编码
// req.setCharacterEncoding("utf-8");
//获取用户名 getParameter(key)里面的key就是input标签里面的name的值
String username = req.getParameter("username");
System.out.println(username);
//获取用户的密码
String userpwd = req.getParameter("passwd");
//获取复选框的值
String [] userlikes=req.getParameterValues("userlike");
List<String> list = Arrays.asList(userlikes);
//获取表单中所有的name的值即所有的key
Enumeration<String> parameterNames = req.getParameterNames();
List<String> paraList =new ArrayList<>();
while (parameterNames.hasMoreElements()){
paraList.add(parameterNames.nextElement());
}
//使用Map结构获取提交的表单的数据
Map<String, String[]> parameterMap = req.getParameterMap();
//遍历Map获取key和Value
Iterator<Map.Entry<String,String[]>> iterator =parameterMap.entrySet().iterator();
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw= resp.getWriter();
pw.println("username:"+username);
pw.println("userpasswd:"+userpwd);
pw.println("UserLikes:"+list);
pw.println("Name:"+paraList);
//遍历迭代器,获取表单中的所有的key和value
while (iterator.hasNext()){
Map.Entry<String,String[]> entry = iterator.next();
String key = entry.getKey();;
String value[] =entry.getValue();
pw.println(key+" = "+Arrays.asList(value));
}
pw.flush();
pw.close();
}
}
在html的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- action表单提交的地址 method提交的方式post-->
<form action="getRequestData.do" method="post">
账号:<input type="text" name="username"> <br/>
密码:<input type="password" name="passwd"> <br/>
爱好:<input type="checkbox" name="userlike" value="Sport" />体育<br/>
<input type="checkbox" name="userlike" value="Sport" />音乐<br/>
<input type="checkbox" name="userlike" value="Sport" />羽毛球<br/>
<input type="checkbox" name="userlike" value="Sport" />乒乓球<br/>
<input type="submit" value="ok">
</form>
</body>
</html>
FilterConfig对象的使用
FilterConfig对象是用来读取中初始化参数的对象。该对象通过参数传递到init方法中,用于读取初始化参数。filterConfig.getInitParameter("name")通过name获取对应的value。filterConfig.getInitParameterNames()返回该Filter中所有中的值。
编写web.xml
<!-- filterConfig对象的使用配置-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.itbaizhan.EncodingFilter</filter-class>
<init-param>
<param-name>code</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
编写Servlet
package com.itbaizhan;
import javax.servlet.*;
import java.io.IOException;
/**
* 设置请求编码的过滤器
*/
public class EncodingFilter implements Filter {
//设置默认的编码
private String defaultCoding = "utf-8";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 通过ServletConfig对像读取这个init-param标签当中的key获取value
String code = filterConfig.getInitParameter("code");
if (code !=null && code.length()!=0){
this.defaultCoding=code;
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置请求的编码
servletRequest.setCharacterEncoding(this.defaultCoding);
//不建议设置响应的编码,因为业务的类型不确定
//设置响应的编码
// servletResponse.setCharacterEncoding("utf-8");
//对请求做放行的处理
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
FilterChain过滤器链
Filter技术的特点是在对请求或响应做预处理时,可实现“插拔式”的程序设计。我们可以根据自己需求添加多个Filter,也可以根据需求去掉某个Filter,通过修改web.xml文件即可实现。那么如果有多个过滤器对某个请求及响应进行过滤,那么这组过滤器就称为过滤器链。
Filter执行顺序
则按照在web.xml文件中配置的上下顺序来决定先后。在上的先执行,在下的后执行。
基于注解式开发Filter
Filter支持注解式开发,通过@WebFilter注解替代web.xml中Filter的配置。
按照名字根据字典的顺序进行执行
在web.xml中的Filter的执行优先级要高于注解式的优先级
编写的Fliter
package com.itbaizhan;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* 基于注解式开发Filter
*/
@WebFilter("/*")
public class AnnotationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Annotation Filter....");
//对请求放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
package com.itbaizhan;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(urlPatterns = "/*",initParams = {@WebInitParam(name = "key",value = "value")})
public class BaizhanFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println(filterConfig.getInitParameter("key"));
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("BaizhanFiltr start....");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Filter的生命周期
Filter的生命周期是由容器管理的。当容器启动时会实例化Filter并调用init方法完成初始化动作。当客户端浏览器发送请求时,容器会启动一个新的线程来处理请求,如果请求的URL能够被过滤器所匹配,那么则先调用过滤器中 的doFilter方法,再根据是否有chain.doFilter的指令,决定是否继续请求目标资源。当容器关闭时会销毁Filter对象,在销毁之前会调用destroy方法。
Listener监听器
监听器用于监听web应用中某些对象的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器会自动调用监听器对象中的方法。
监听器分类
按监听的对象划分,可以分为:ServletContext对象生命周期监听器与属性操作监听器;HttpSession对象生命周期监听器与属性操作监听器;ServletRequest对象生命周期监听器与属性操作监听器;
ServletContext对象的生命周期监听器
ServletContextListener接口定义了ServletContext对象生命周期的监听行为。
void contextInitialized(ServletContextEvent sce)ServletContext对象创建之后会触发该监听方法,并将ServletContext对象传递到该方法中。
void contextDestroyed(ServletContextEvent sce)ServletContext对象在销毁之前会触发该监听方法,并将ServletContext对象传递到该方法中。
监听器创建好了后不能够直接的用,还需要在web.xml中做监听器的配置
编写Listener
package com.itbaizhan.Listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ServletContextLifecycleListener implements ServletContextListener {
/**
* 监听servletContext对象创建的监听的方法
* @param sce
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc= sce.getServletContext();
System.out.println(sc);
System.out.println("ServletText init..........");
}
/**
*
* 监听servletContext对象销毁的监听的方法
* @param sce
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
ServletContext sc= sce.getServletContext();
System.out.println(sc);
System.out.println("servletContext Destroy......");
}
}
web.xml
<listener>
<listener-class>com.itbaizhan.Listener.ServletContextLifecycleListener</listener-class>
</listener>
ServletContext对象的属性操作监听器
ServletContextAttributeListener接口定义了对于ServletContext对象属性操作的监听行为。
void attributeAdded(ServletContextAttributeEvent scae)向ServletContext对象中添加属性时会触发该监听方法,并将ServletContext对象传递到该方法中。触发事件的方法
servletContext.setAttribute("key","value")。
void attributeRemoved(ServletContextAttributeEvent scae)当从ServletContext对象中删除属性时会触发该监听方法,并将ServletContext对象传递到该方法中。触发事件方法servletContext.removeAttribute("key")。
void attributeReplaced(ServletContextAttributeEvent scae)
当从ServletContext对象中属性的值发生替换时会触发该监听方法,并将ServletContext对象传递到该方法中。触发事件的方法servletContext.setAttribute("key","value")。
编写的Listeners
package com.itbaizhan.Listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* servletContext属性操作监听器
*
*/
public class ServletContextAttrListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("------------------start Added----------------------");
System.out.println("Name:"+scae.getName()+" Value:"+scae.getValue());
System.out.println(scae.getServletContext());
System.out.println("--------------------End Added--------------------------------");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("------------------start removed----------------------");
System.out.println("Name:"+scae.getName()+" Value:"+scae.getValue());
System.out.println(scae.getServletContext());
System.out.println("--------------------End removed--------------------------------");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("------------------start replaced----------------------");
System.out.println("Name:"+scae.getName()+" Value:"+scae.getValue());
System.out.println(scae.getServletContext());
System.out.println("--------------------End replaced--------------------------------");
}
}
编写的web.xml
<listener>
<listener-class>com.itbaizhan.Listener.ServletContextAttrListener</listener-class>
</listener>
编写的测试的servlet
package com.itbaizhan.Listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* servletContext属性监听器的测试servlet
*/
@WebServlet("/attr.do")
public class ServletContextAttrServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("key","BJSXT");
servletContext.setAttribute("key","ITBZ");
servletContext.removeAttribute("key");
}
}
HttpSession对象的生命周期监听器
HttpSessionListener接口定义了HttpSession对象生命周期的监听行为。
void sessionCreated(HttpSessionEvent se)HttpSession对象创建后会触发该监听方法,并将已创建HttpSession对象传递到该方法中。
void sessionDestroyed(HttpSessionEvent se)HttpSession对象在销毁之前会触发该监听方法,并将要销毁的HttpSession对象传递到该方法中。
编写的servlet
package com.itbaizhan.Listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* HttpSession对象的声明周期监听器
*/
public class HttpSessionLifecycleListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("sessionCreated");
System.out.println(se.getSession());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("sessionDestroyed");
System.out.println(se.getSession());
}
}
编写web.xml
<listener>
<listener-class>com.itbaizhan.Listener.HttpSessionLifecycleListener</listener-class>
</listener>
HttpSession对象的属性操作监听器
HttpSessionAttributeListener接口定义了对于HttpSession对象属性操作的监听行为。
void attributeAdded(HttpSessionBindingEvent se)向HttpSession对象中添加属性时会触发该监听方法,并将HttpSession对象传递到该方法中。触发事件的方法HttpSession.setAttribute("key","value")。
void attributeRemoved(HttpSessionBindingEvent se)当从HttpSession对象中删除属性时会触发该监听方法,并将HttpSession对象传递到该方法中。触发事件方法HttpSession.removeAttribute("key")。
void attributeReplaced(HttpSessionBindingEvent se)当从HttpSession对象中属性的值发生替换时会触发该监听方法,并将HttpSession对象传递到该方法中。触发事件的方法HttpSession.setAttribute("key","value")。
编写属性监听器
package com.itbaizhan.Listener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
/**
* HttpSession属性监听器
*/
public class HttpSessionAttrListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("------------------attributeAdded---------------Start Added----------");
System.out.println("Name:"+se.getName()+" value"+se.getValue());
System.out.println(se.getSession());
System.out.println("------------------attributeAdded---------------End Added----------");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("------------------attributeRemoved---------------Start remove----------");
System.out.println("Name:"+se.getName()+" value"+se.getValue());
System.out.println(se.getSession());
System.out.println("------------------attributeRemoved---------------End remove----------");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("------------------attributeReplaced---------------Start replace----------");
System.out.println("Name:"+se.getName()+" value"+se.getValue());
System.out.println(se.getSession());
System.out.println("------------------attributeReplaced---------------End replace----------");
}
}
编写web.xml
<listener>
<listener-class>com.itbaizhan.Listener.HttpSessionAttrListener</listener-class>
</listener>
编写测试的servlet
package com.itbaizhan.Listener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 测试HttpSession属性监听器
*/
@WebServlet("/sessionAttr.do")
public class HttpSessionAttrServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取HttpSession对象
HttpSession session= req.getSession();
session.setAttribute("key","BJSXT");
session.setAttribute("key","ITBZ");
session.removeAttribute("key");
}
}
HttpServletRequest对象的生命周期监听器
ServletRequestListener接口定义了ServletRequest(是HttpServletRequest接口的父接口类型)对象生命周期的监听行为。
void requestInitialized(ServletRequestEvent sre)
HttpServletRequest对象创建后会触发该监听方法,并将已创建HttpServletRequest对象传递到该方法中。
void requestDestroyed(ServletRequestEvent sre)
HttpServletRequest对象在销毁之前会触发该监听方法,并将要销毁HttpServletRequest对象传递到该方法中。
package com.itbaizhan.Listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
/**
* 监听HttpServletRequest生命周期的监听器
*/
public class HttpServletRequestLifecycleListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("- ==================Start requestDestroyed=====================--");
System.out.println((HttpServletRequest)sre.getServletRequest());
System.out.println("- ==================End requestDestroyed=====================--");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("- ==================Start Initialized=====================--");
System.out.println((HttpServletRequest)sre.getServletRequest());
System.out.println("- ==================End Initialized=====================--");
}
}
编写web.xml
<listener>
<listener-class>com.itbaizhan.Listener.HttpServletRequestLifecycleListener</listener-class>
</listener>
HttpServletRequest对象的属性操作监听器
ServletRequestAttributeListener接口定义了对于HttpServletRequest对象属性操作的监听行为。
void attributeAdded(ServletRequestAttributeEvent srae)向HttpServletRequest对象中添加属性时会触发该监听方法,并将HttpServletRequest对象传递到该方法中。触发事件的方法HttpServletRequest.setAttribute("key","value")。
void attributeRemoved(ServletRequestAttributeEvent srae)
当从HttpServletRequest对象中删除属性时会触发该监听方法,并将HttpServletRequest对象传递到该方法中。触发事件方法HttpServletRequest.removeAttribute("key")。
void attributeReplaced(ServletRequestAttributeEvent srae)
当从HttpServletRequest对象中属性的值发生替换时会触发该监听方法,并将HttpServletRequest对象传递到该方法中。触发事件的方法HttpServletRequest.setAttribute("key","value")。
基于注解式开发监听器
Listener支持注解式开发,通过@WebListener注解替代web.xml中Listener的配置。
Filter与Listener设计模式
知其然,知其所以然”。Filter的设计模式在Servlet的Filter中使用的责任链设计模式。责任链模式特点责任链(Chain of Responsibility):责任链模式也叫职责链模式,是一种对象行为模式。在责任链模式里,很多对象由每一个对象对其下一个对象的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不需要知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
责任链的优缺点
优点:降低了对象之间的耦合度。增强了系统的可扩展性。增强了给对象指派职责的灵活性。责任链简化了对象之间的连接。责任分担。每个类只需要处理自己该处理的工作。
缺点:不能保证请求一定被接收。对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。可能会由于责任链的错误设置而导致系统出错,如可能会造成循环调用。
Listener的设计模式
在Servlet的Listener中使用的观察者设计模式。
观察者模式的特点
观察者模式(Observer Pattern):观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。观察者模式的优缺点
优点:观察者和被观察者是抽象耦合的。建立一套触发机制。
缺点:如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。