HttpServletResponse
HttpServletResponse继承了ServletResponse接口,并提供了与Http协议有关的方法,这些方法的主要功能是设置HTTP状态码和管理Cookie。HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法
HttpServletResponse对象可以向客户端发送三种类型的数据:
a.响应头(Response headers)
addHeader(String name,String value) 将指定的名字和值加入到响应的头信息中
setHeader(String name,String value) 将给出的名字和值设置响应的头部
setContentType(String ContentType)设置响应的MIME类型 ,页面的设置文本类型,获取或设置输出流的 HTTP MIME 类型。输出流的 HTTP MIME类型。默认值为“text/html”。
MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式
setLocale(locale loc):用于设置响应消息的本地化信息
setCharacterEncoding(String charset):输出内容使用的字符编码。
比setLocale(locale loc),setContentType(String ContentType)优先级高
encodeURL(String url) 编码指定的URL
setDateHeader(String name,long date 将给出的名字和日期设置响应的头部
response.setHeader(“Refresh”,”2;url=”http://www.baidu.com”); 页面的刷新
HttpServletResponse.sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程
b.状态码(Protocol—Status code—Description)
setStatus(int sc) 给当前响应设置状态码
sendError(int sc) 使用指定状态码发送一个错误到客户端
c.实体数据(Entity body )
消息实体内容 通过输出流对象进行设置,用以下两个方法:
Response.getOutputStream() 字节输出流对象
Response.getWriter() 字符的输出流对象
getOutputStream和getWriter方法的比较
(1)getOutputStream方法用于返回Servlet引擎创建的字节输出流对象,Servlet程序可以按字节形式输出响应正文。
String data = "哈哈";
ServletOutputStream out = response.getOutputStream();
out.write(data.getBytes());
(2)getWriter方法用于返回Servlet引擎创建的字符输出流对象,Servlet程序可以按字符形式输出响应正文。
PrintWriter out1 = response.getWriter();
out1.write(data);
(3)getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。要不会出现错误java.lang.IllegalStateException
(4)getOutputStream方法返回的是字节输出流对象的类型为ServletOutputStream,它可以直接输出字节数组中的二进制数据。
(5)getWriter方法将Servlet引擎的数据缓冲区包装成PrintWriter类型的字符输出流对象后返回,PrintWriter对象可以直接输出字符文本内容。
(6)Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
(7)Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。
注:out.close();系统会自己释放,但一般写上
选择getOutputStream和getWrite方法的要点
(1)PrintWriter对象输出字符文本内容时,它内部还是将字符串转换成了某种字符集编码的字节数组后再进行输出,使用PrintWriter对象的好处就是不用编程人员自己来完成字符串到字节数组的转换。
(2)使用ServletOutputStream对象也能输出内容全为文本字符的网页文档,但是,如果网页文档内容是在Servlet程序内部使用文本字符串动态拼凑和创建出来的,则需要先将字符文本转换成字节数组后输出。
(3)如果一个网页文档内容全部为字符文本,但是这些内容可以直接从一个字节输入流中读取出来,然后再原封不动地输出到客户端,那么就应该使用ServletOutputStream对象直接进行输出,而不要使用PrintWriter对象进行输出。
向客户端写入中文
使用OutputStream向客户端写入中文:
String data = "中国";
OutputStream stream = response.getOutputStream();//获取一个向Response对象写入数据的流,当tomcat服务器进行响应的时候,会将Response中的数据写给浏览器
stream.write(data.getBytes("UTF-8"));//此时在html页面会出现乱码,
正确代码如下:
response.setHeader("Content-type","text/html;charset=UTF-8");//向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8
String data = "中国";
OutputStream stream = response.getOutputStream();
stream.write(data.getBytes("UTF-8"));
使用PrintWriter向客户端写入中文:
正确代码如下:
response.setCharacterEncoding("UTF_8");
response.setHeader("Content-type","text/html;charset=UTF-8");
//response.setContentType("text/html;charset=UTF-8");同上两句代码作用一样
PrintWriter writer = response.getWriter();
writer.write("中国");
注意在获取PrintWriter输出流之前首先使用"response.setCharacterEncoding(charset)"设置字符以什么样的编码输出到浏览器,如:response.setCharacterEncoding("UTF-8");设置将字符以"UTF-8"编码输出到客户端浏览器,然后再使用response.getWriter();获取PrintWriter输出流,这两个步骤不能颠倒
随机验证码
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int width = 120;
int height = 25;
//创建一副内存图像
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//得到画笔
Graphics g = image.getGraphics();
//开始画
//边线
g.setColor(Color.BLUE);
g.drawRect(0, 0, width, height);
//填充背景色
g.setColor(Color.YELLOW);
g.fillRect(1, 1, width-2, height-2);
//划干扰线
g.setColor(Color.GRAY);
Random r = new Random();
for(int i=0;i<9;i++)
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
//验证码
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.ITALIC|Font.BOLD, 19));
char[] chars = ("0123456789asdfghjkiqirADHBFGIUHDIFJKBNJ").toCharArary();
StringBuilder sb = new StringBuilder();
int x = 20;
for(int i=0;i<4;i++){
int pos = r.nextInt(chars.length);
char c = chars[pos];
sb.append(c+"");
g.drawString(r.nextInt(10)+"", x,20 );
}
g.drawString(sb.toString(),20,20 );//写入验证码
//输出
response.setHeader("Expires", "-1");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
ImageIO.write(image, "jpg", response.getOutputStream());
}
定时刷新
//定时刷新到别处
private void test2(HttpServletResponse response) throws IOException {
response.setContentType("text/htm;charset=UTF-8");
response.setHeader("Refresh", "5;URL=http://www.Baidu.com");
response.getWriter().write("登录成功,5秒后跳转到主页");
}
//定时刷新自己
Random r = new Random();
//response.setHeader("Refresh", "1");
response.setIntHeader("Refresh", 1);
response.getWriter().write(r.nextInt()+"");
}
缓存
//控制缓存的时间
//静态资源需要控制缓存时间
//动态资源一般不要缓存
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "哈哈哈";
//让他缓存1个小时
response.setDateHeader("Expires", System.currentTimeMillis()+1*60*60*1000);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(data);
}
禁止浏览器缓存页面
Expires: -1 控制时间的
Cache-Control: no-cache (1.1)
Pragma: no-cache (1.0)
三头一块用,用于告知浏览器,不要缓存。
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
重定向
response.sendRedirect("http://www.baidu.com");
HttpServletRequest
公共接口类HttpServletRequest继承自ServletRequest.客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。所有的信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。
一个 HTTP 请求包含以下三部分:
a.请求地址(URL)
b.请求头(Request headers)
c.实体数据(Entity body)
常用方法
1.获得客户机信息
getRequestURL方法返回客户端发出请求时的完整URL。
getRequestURI方法返回请求行中的资源名部分。
getQueryString 方法返回请求行中的参数部分。
getRemoteAddr方法返回发出请求的客户机的IP地址
getRemoteHost方法返回发出请求的客户机的完整主机名
getRemotePort方法返回客户机所使用的网络端口号
getLocalAddr方法返回WEB服务器的IP地址。
getLocalName方法返回WEB服务器的主机名
getMethod得到客户机请求方式
getServerPath()获取请求的文件的路径
2.获得客户机请求头
getHeader(string name)方法
getHeaders(String name)方法
getHeaderNames方法
3. 获得客户机请求参数(客户端提交的数据)
getParameter(name)方法 获取请求中的参数,该参数是由name指定的
getParameterValues(String name)方法 获取指定名称参数的所有值数组。它适用于一个参数名对应多个值的情况。如页面表单中的复选框,多选列表提交的值。
getParameterNames方法 返回一个包含请求消息中的所有参数名的Enumeration对象。通过遍历这个Enumeration对象,就可以获取请求消息中所有的参数名。
getCharacterEncoding() 返回请求的字符编码方式
getAttributeNames()返回当前请求的所有属性的名字集合赋值:setAttribute()
getAttribute(String name) 返回name指定的属性值
getsession()返回和客户端相关的session,如果没有给客户端分配session,则返回null
getParameterMap():返回一个保存了请求消息中的所有参数名和值的Map对象。Map对象的key是字符串类型的参数名,value是这个参数所对应的Object类型的值数组
RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
request.setCharacterEncoding("utf-8");
HttpServletRequest中的常用方法
//HttpServletRequest中的常用方法
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method = request.getMethod();//请求方式
String uri = request.getRequestURI();
String url = request.getRequestURL().toString();
String protocal = request.getProtocol();//客户端使用的协议
String remoteIp = request.getRemoteAddr();//来访者的ip
int port = request.getRemotePort();// 随机的
String queryString = request.getQueryString();//GET方式:
System.out.println(method);
System.out.println(uri);
System.out.println(url);
System.out.println(protocal);
System.out.println(remoteIp);
System.out.println(port);
System.out.println(queryString);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletInputStream in = request.getInputStream();
int len = -1;
byte b[] = new byte[1024];
while((len=in.read(b))!=-1){
System.out.println(new String(b,0,len));
}
in.close();
}
获取消息头消息
//得到所有的消息头
Enumeration e = request.getHeaderNames();
while(e.hasMoreElements()){
String headerName = e.nextElement();//透明称
Enumeration headerValues = request.getHeaders(headerName);
while(headerValues.hasMoreElements()){
System.out.println(headerName+":"+headerValues.nextElement());
//http协议是允许头有重复的情况,多个重名的头
private void test2(HttpServletRequest request) {
Enumeration e = request.getHeaders("Accept-Encoding");//得到的头值
while(e.hasMoreElements()){
String headerValue = e.nextElement();
System.out.println(headerValue);
//得到指定请求消息头的值。如果没有该头,返回null
private void test1(HttpServletRequest request) {
String supportEncoding = request.getHeader("Accept-Encoding");
if(supportEncoding.contains("gzip")){
System.out.println("支持gzip压缩");
}else{
System.out.println("不支持gzip压缩");
}
流的形式获取请求参数
//以输入流的形式接收请求正文:POST
//一般情况下用不着,文件上传时使用。
public class RequestDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletInputStream in = request.getInputStream();
int len = -1;
byte b[] = new byte[1024];
while((len=in.read(b))!=-1){
System.out.println(new String(b,0,len));
}
in.close();
}
转发与路径
//ServletContext:地址的写法。必须以"/",代表当前应用。(应用开头的绝对路径)
// RequestDispatcher rd = getServletContext().getRequestDispatcher("/servlet/RequestDemo7");
//绝对路径
// RequestDispatcher rd = request.getRequestDispatcher("/servlet/RequestDemo7");
//相对路径
RequestDispatcher rd = request.getRequestDispatcher("RequestDemo7");
rd.forward(request, response);
包含
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("我喜欢");
RequestDispatcher rd = request.getRequestDispatcher("/servlet/RequestDemo9");
rd.include(request, response);
}
转发:到别的页面,地址栏不变
包含:别的页面到本页面,地址栏不变
请求消息体的相关方法
ServletInputStream in= request.getInputStream();
BufferedReader br = request.getReader();
封装请求参数
//以下内容只用简单的程序开发
//获取单一的请求参数的值(用户所有的输入都是String)
String username = request.getParameter("username");//不区分get还是post的
String password = request.getParameter("password");
System.out.println(username+":"+password);
//获取重名请求参数的值
String username = request.getParameter("username");//不区分get还是post的
String passwords[] = request.getParameterValues("password");//获取重名的请求参数值
System.out.println(username+":"+Arrays.asList(passwords));
//获取所有的请求参数名和值
Enumeration e = request.getParameterNames();//参数名
while(e.hasMoreElements()){
String paramName = e.nextElement();
String values [] = request.getParameterValues(paramName);
System.out.println(paramName+"="+Arrays.asList(values));
//获取所有的请求参数名和值
Enumeration e = request.getParameterNames();//参数名
while(e.hasMoreElements()){
String paramName = e.nextElement();
String values [] = request.getParameterValues(paramName);
System.out.println(paramName+"="+Arrays.asList(values));
//把请求参数的值封装到JavaBean中
//表单的输入域的取值和JavaBean中的属性(getter和setter方法)保持一致
Enumeration e = request.getParameterNames();//参数名
User user = new User();
System.out.println("封装前:"+user);
while(e.hasMoreElements()){
String paramName = e.nextElement();//即是JavaBean中的属性名称
String paramValue = request.getParameter(paramName);
//setUsername(paramValue); setPassword(paramValue);
//JavaBean的内省
try {
PropertyDescriptor pd = new PropertyDescriptor(paramName, User.class);
Method m = pd.getWriteMethod();//setter方法
m.invoke(user, paramValue);
} catch (Exception e1) {
e1.printStackTrace();
}
}
System.out.println("封装后:"+user);
-----------------------------------------------------------------------
//getParameterMap获取参数
//key:请求参数名 value:请求参数值数组
Map map = request.getParameterMap();
for(Map.Entry me:map.entrySet()){
System.out.println(me.getKey()+"="+Arrays.asList(me.getValue()));
}
------------------------------------------------------------------------
//getParameterMap获取参数:封装到JavaBean中
//key:请求参数名 value:请求参数值数组
Map map = request.getParameterMap();
User user = new User();
for(Map.Entry me:map.entrySet()){
String paramName = me.getKey();//参数名称
String paramValues[] = me.getValue();//参数值
try {
PropertyDescriptor pd = new PropertyDescriptor(paramName, User.class);
Method m = pd.getWriteMethod();//setter方法
if(paramValues.length>1){
m.invoke(user, (Object)paramValues);//参考补充视频:反射main方法
}else{
m.invoke(user, paramValues);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
System.out.println(user);
---------------------------------------------------------------------------
//借助BeanUtil框架
User user = new User();
System.out.println("封装前:"+user);
try {
BeanUtils.populate(user, request.getParameterMap());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("封装后:"+user);
中文乱码问题
设置编码的两种方式:
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
系统默认的编码方式为ISO8859-1,如果没有指定字符编码,则输出的都是乱码,而且ISO8859-1不支持中文,所以不管浏览器在解码的时候用的是什么字符集编码,在浏览器上的都是乱码。
解决办法如下
Post方式提交出现乱码
request.setCharacterEncoding("UTF-8");
Get方式提交出现乱码
String name = request.getParameter("name");//接收数据
name =new String(name.getBytes("ISO8859-1"), "UTF-8") ;//获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题