您的位置:首页 > 理论基础 > 计算机网络

JavaWeb学习四(HttpServletResponse和HttpServletRequest)

2017-05-04 15:15 399 查看

一.服务器处理请求流程

1.请求响应流程图



服务器每次收到请求时,都会为这个请求开辟一个新的线程

服务器会把客户端的请求数据封装到request对象中

request就是请求数据的载体!(筷子)

服务器还会创建response对象,这个对象与客户端连接在一起

它可以用来向客户端发送响应(手机)

二.HttpServletResponse

ServletResponse–> 与协议无关的类型

HttpServletResponse –>与Http协议相关的类型

1.状态码

sendError(int sc) –>发送错误状态码,例如404 500

sendError(int sc,String msg) –>发送错误状态码,还可以带一个错误信息

setStatus(int sc)–> 发送成功的状态码 可以用来发送302

public class CServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(404,"成都东软校园网无法访问");

}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}


访问此Servlet效果如下图:



2.响应头

Content-Type Refresh Location等等

头就是一个键值对,可能会存在一个头(一个名称 一个值),也可能会存在一个头(一个名称 多个值)

setHeader(String name,String value):适用于单值的响应头

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("aaa","AA");
response.setStatus(200);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}




addHeader(String name,String value):使用于多值的响应头

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("aaa","AAA");
response.addHeader("aaa", "AA");
response.addHeader("aaa", "A");
response.setStatus(200);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}




setIntHeader(String name,int value):适用于单值的int类型的响应头

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setIntHeader("aaa",1);
response.setStatus(200);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}




addIntHeader(String name,int value):适用于多值的int类型的响应头

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addIntHeader("aaa",1);
response.addIntHeader("aaa",22);
response.addIntHeader("aaa",333);
response.setStatus(200);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}




setDateHeader(String name,long value):适用于单值的毫秒类型的响应头

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setDateHeader("expires",60*60*24*1000);//缓存24小时
response.setStatus(200);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}




不过注意一般在开发的时候会这么设置,缓存大多自然不好

response.setDateHeader("expires",-1);//设置过期时间为-1


addDateHeader(String name,long value):适用于多值的毫秒类型的响应头

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addDateHeader("expires",60*60*24*1000);//缓存24小时
response.addDateHeader("expires",60*60*24*10000);//缓存240小时
response.setStatus(200);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}




3.案例

(1).发送302,设置Location头,完成重定向

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("DServlet...");
response.setHeader("Location","/javaweb2/EServlet");
response.setStatus(302);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}


public class EServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("EServlet...");
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}


访问DServlet,控制台打印出

DServlet...
EServlet...




大致图解



(2).定时刷新,设置Refresh头,你可以把它理解成,定时的重定向

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setContentType("text/html;charset=utf-8");

PrintWriter printWriter=response.getWriter();

printWriter.println("您好,5秒钟将进入重定向");

response.setHeader("Refresh","5;URL=/javaweb2/EServlet");
}

}


public class EServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setContentType("text/html;charset=utf-8");
response.getWriter().println("你看到不是乱码!");
}

}




(3).禁止浏览器缓存

public class FServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Cache-Control","no-cache");
response.setHeader("pragma","no-cache");
response.setDateHeader("expires",-1);
response.getWriter().print("hello world");
}

}


注意:
<meta>标签可以代替响应头


<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
<meta http-equiv="Content-Type" content="Cache-Control"; charset="no-cache">
...


4.响应体

响应体通常是html,也可以是图片

response的两个流

ServletOutputStream 用来向客户端发送字节数据

ServletOutputStream out=response.getOutputStream();


PrintWriter: 用来向客户端发送字符数据 需要设置编码

PrintWriter writer=response.getWriter();


public class GServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String ss="hello world";
byte[] bys=ss.getBytes();
response.getOutputStream().write(bys);

String path="‪E:/F/黑黑.jpg";
FileInputStream fis=new FileInputStream(path);
byte[] byss=IOUtils.toByteArray(fis);//将图片转换成字节数组
response.getOutputStream().write(byss);
}

}


注意两个流不能同时使用

5.直接进行重定向

public class DServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("DServlet...");
response.sendRedirect("/javaweb2/EServlet");//直接进行重定向的方法
}

}


public class EServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("EServlet...");
}

}


控制台打印

DServlet...
EServlet...


三.HttpServletRequest(封装了客户端所有的请求数据)

1.请求协议

请求行

请求头

空行

请求体(GET提交方式是没有请求体的)

2.常用方法

(1).获取常用信息

A.获取客户端ip

request.getRemoteAddr();


B.获取请求方式

request.getMethod();//可能是POST 也可能是GET


(2).获取HTTP请求头

String getHeader(String name);//适用于单值头


int getIntHeader(Stirng name);//适用于单值int类型的请求头


long getDateHeader(String name);//适用于单值毫秒类型的请求头


Enumeration <String> getHeaders(String name);//适用于多值请求头


举例

public class AServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String addr=request.getRemoteAddr();
String method=request.getMethod();
String userAgent=request.getHeader("user-Agent");

System.out.println("addr:"+addr);
System.out.println("请求方式:"+method);
System.out.println("user-Agent:"+userAgent);
}

}


打印

addr:0:0:0:0:0:0:0:1
请求方式:GET
user-Agent:Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko


user-Agent包括了很多信息,访问资源浏览器的信息,系统信息等

(3).获取请求URL

String getScheme():获取协议 http

String getServerName():获取服务器名 localhost

String getServerPort():获取服务器端口 8080

String getContextPath():获取项目名

String getServletPath():获取Servlet路径

String getQueryString():获取参数部分 即问号后面的部分

String getRequestURI():获取请求URI

StringBuffer getRequestURL():获取请求URL



举例

public class BServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String http=request.getScheme();
String ServerName=request.getServerName();
int Serverport=request.getServerPort();
String ContextPath=request.getContextPath();
String ServletPath=request.getServletPath();
String QueryString=request.getQueryString();
String uri=request.getRequestURI();
StringBuffer url=request.getRequestURL();

System.out.println("协议名:"+http);
System.out.println("服务器名:"+ServerName);
System.out.println("服务器端口:"+Serverport);
System.out.println("项目名:"+ContextPath);
System.out.println("servlet的路径:"+ServletPath);
System.out.println("参数:"+QueryString);
System.out.println("uri:"+uri);
System.out.println("url:"+url.toString());

}

}


打印

协议名:http
服务器名:localhost
服务器端口:8080
项目名:/javaweb3
servlet的路径:/BServlet
参数:null     //因为你是get请求所以没有参数
uri:/javaweb3/BServlet
url:http://localhost:8080/javaweb3/BServlet


<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/javaweb3/BServlet" method="get">
<input type="text" name="text"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>


打印

协议名:http
服务器名:localhost
服务器端口:8080
项目名:/javaweb3
servlet的路径:/BServlet
参数:text=1444
uri:/javaweb3/BServlet
url:http://localhost:8080/javaweb3/BServlet


(4).防盗链

如果请求不是通过本站的超链接发出的,发送错误状态码404,Referer,这个请求头表示请求的来源!

public class CServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String Referer=request.getHeader("Referer");
System.out.println(Referer);
if(Referer==null||Referer.contains("localhost")) {//直接访问Referer值是null
response.sendRedirect(request.getContextPath()+"/DServlet");
}else {
response.sendError(404, "滚开");
}

}
}


(5).获取请求参数

请求参数是由客户端发送给服务器的 有可能是在请求体中(POST)

String getParameter(String name):获取指定名称的请求参数值,适用于单值请求参数

String [] getParameterValues(String name):获取指定名称的请求参数值,适用于多值请求参数

Enumeration
<String>
getParameterNames():获取所有请求参数名称

Map
<String,String[]>
getParameterMap():获取所有请求参数,其中Key为参数名,value为参数值

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/javaweb3/EServlet">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
性别:<input type="radio" name="sex" value="nan">男
<input type="radio" name="sex" value="nv">女<br/>
爱好:<input type="checkbox" name="love" value="ppq">乒乓球
<input type="checkbox" name="love" value="lq">篮球
<input type="checkbox" name="love" value="ymq">羽毛球<br/>
<input type="submit" value="提交">

</form>
</body>
</html>


public class EServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getParameter("username");
String password=request.getParameter("password");

System.out.println("username:"+username);
System.out.println("password:"+password);

String [] loves=request.getParameterValues("love");
for(String s:loves) {
System.out.println("love:"+s);
}

Enumeration<String> enumeration=request.getParameterNames();

while(enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}

Map<String,String[]> map=request.getParameterMap();

for(String name:map.keySet()) {
String [] values=map.get(name);
System.out.println(name+":"+Arrays.toString(values));
}
}

}


打印

username:123
password:123
love:ppq
love:lq
love:ymq
username
password
sex
love
username:[123]
password:[123]
sex:[nan]
love:[ppq, lq, ymq]


(6).请求转发和请求包含

RequestDispatcher rd=request.getRequestDispatcher("/MyServlet")
使用request获取RequestDispatcher对象,方法的参数是被转发或包含的Servlet路径

A.请求转发

public class OneServlet extends HttpServlet {

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("OneServlet...");
resp.setHeader("aaa","AAA");//设置响应头

resp.getWriter().print("aaaaaaa");//设置响应体

req.getRequestDispatcher("/TwoServlet").forward(req, resp);

}
}


public class TwoServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("TwoServlet...");
response.getWriter().print("bbbbbb");//设置响应体

}

}




总结

由下一个Servlet完成响应体,当前Servlet可以设置响应头(留头不留体)

如果把OneServlet改成如下

public class OneServlet extends HttpServlet {

@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("OneServlet...");
resp.setHeader("aaa","AAA");

for(int i=0;i<1024*24+1;i++) {
resp.getWriter().print("a");
}
//相当于调用了TwoServlet的service的方法
req.getRequestDispatcher("/TwoServlet").forward(req, resp);

}
}


为什么打印出了?不是留头不留体嘛?



看吧!控制台还是报错了的!



总结

在请求转发的时候,最好不要做过多的操作,过多的操作情况下,就好别使用转发

B.请求转发

public class OneServlets extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("OneServlets...");
response.setHeader("aaa","AAA");

response.getWriter().print("OneServlet one!!!");

request.getRequestDispatcher("/TwoServlets").include(request, response);

}

}


public class TwoServlets extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("TwoServlets...");

response.getWriter().print("TwoServlet two!!!");
}

}




总结

由两个Servlet共同未完成响应体(都留)

无论是请求转发还是请求包含,都在一个请求范围内,使用同一个request和response!

(7).request域

Servlet中三大域对象: request session application

void setAttribute(String name,Object value)

object getAttribute(String name)

void removeAttribute(String name)



同一请求范围内使用request.setAttribute(),request.getAttribute()来传值

(8).请求转发和重定向的区别

请求转发是一个请求一次响应,而后者是两次请求两次响应

请求转发地址栏不变化,而后者显示后一个请求的地址

请求转发只能转发到本项目其他Servlet,而后者不只能重定向到本项目的其他Servlet,还能定向到其他项目

请求转发是服务器端行为,只需给出转发的Servlet路径,而后者需要给出requestURI ,即包含项目名

请求转发和重定向效率,转发高 ,因为是一个请求

需要地址栏发生变化,那么必须重定向

需要在下一个Servlet中获取request域中的数据,必须要使用转发

END!!!!!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: