1、respone
response代表响应 , 可以理解为一个空的箱子,我们在里面填入要发送到浏览器的内容. 服务器会把这些内容组装成http响应。
响应首行 协议/版本号 状态码 状态码描述
添加状态码和 描述
voidsetStatus(int sc) 只设置状态码
voidsetStatus(int sc, String sm) 设置状态码和描述
voidsendError(int sc) 只设置状态码,错误的
void sendError(int sc, String msg) 设置状态码和描述
响应头
添加响应头
void setHeader(String name, String value) 设置响应头,如果key一样会覆盖
setIntHeader(Stringname, int value)
setDateHeader(Stringname, long date)
void addHeader(String name, String value) 设置响应头,无论如何都新增.
void addIntHeader(String name, int value)
void addDateHeader(String name, longdate)
响应空行
响应正文
发送字节流
getOutputStream
发送字符流
getWriter
(1)手动向浏览器发送404
response.sendError
public void doGet(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException, IOException {
response.sendError(404, "找到也不告诉你!");
}
(2)重定向
之前:response.setStatus(302);response.setHeader("Location","http://www.baidu.com");
现在:response.sendRedirect("/Day08-response/AServlet");
定向
/*
//1 返回状态码为302
response.setStatus(302);
//2 告诉浏览器去哪找新的地址 发送一个响应头: Location : http://www.baidu.com
//response.setHeader("Location", "http://www.baidu.com");
response.setHeader("Location", "/Day08-response/AServlet");
*/
//-----------------------------------------------------------------
response.sendRedirect("/Day08-response/AServlet");
(3)Refresh头.
设置响应头Refresh参数:5S后刷新到AServlet。
response.setHeader("Refresh","5;url=/Day08-response/AServlet");
//解决乱码
response.setContentType("text/html;charset=utf-8");
//1.设置响应头 为Refresh:5;url=/Day08-response/AServlet
response.setHeader("Refresh", "5;url=/Day08-response/AServlet");
//2.使用字符流发送提示,5秒后跳转
response.getWriter().print("您将在<span id='one' ></span>秒后跳转到AServlet!" +
"<script type='text/javascript'>" +
"var count = 5;" +
"function fun1(){" +
"var span = document.getElementById('one');" +
"span.innerHTML = count--;" +
"" +
"if(count>0){" +
"window.setTimeout(fun1,1000);" +
"}" +
"}" +
"fun1();" +
"</script>");
(4)发送字节流. 发送中文
response发送字节流:
OutputStream os = response.getOutputStream();
解决乱码
方法1:os.write("<meta http-equiv='Content-Type' content='text/html;charset=gbk'>".getBytes());
方法2:response.setHeader("Content-Type", "text/html;charset=utf-8");
public class DServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 获得输出字节流
OutputStream os = response.getOutputStream();
//2 输出中文
os.write("你好 世界!".getBytes("UTF-8"));
//3告诉浏览器使用GBK解码 ==> 乱码
//os.write("<meta http-equiv='Content-Type' content='text/html;charset=gbk'>".getBytes());
response.setHeader("Content-Type", "text/html;charset=utf-8");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
(5)发送字符流. 发送中文
response发送字符流:
PrintWriter pw = response.getWriter();
解决乱码:
方法1:response.setCharacterEncoding("UTF-8");response.setHeader("Content-Type", "text/html;charset=utf-8");
方法2:response.setContentType("text/html;charset=utf-8"); 推荐
字符流和字节流要注意的一个问题:
字节流和字符流一定不能同时使用.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*//控制字符流使用的编码,往上放.在获得字符流的时候,会来取这个编码.如果在取完之后设置,没有效果.
response.setCharacterEncoding("UTF-8");
//告诉浏览器使用什么码表解码
response.setHeader("Content-Type", "text/html;charset=utf-8");*/
//JAVAEE提供了一个方法,这个方法同时可以做 以上两件事.
response.setContentType("text/html;charset=utf-8");
//1 获得字符流
PrintWriter pw = response.getWriter();
//2 发送中文
pw.print("你好 世界!");
//问题: 同时使用两种流 会出现问题
//response.getOutputStream().write("haha".getBytes());
}
(6)使用字节流发送图片
告诉浏览器 发给你的流的MIME类型:
response.setContentType("image/jpeg");
获得图片的输入流(用到servlet知识):
InputStream in = getServletContext().getResourceAsStream("/WEB-INF/001.jpg");
俩流对接:
byte[] buffer = new byte[1024];
int len = 0;
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
out.flush();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//0告诉浏览器 发给你的流的MIME类型.
response.setContentType("image/jpeg");
//1 获得图片的输入流
InputStream in = getServletContext().getResourceAsStream("/WEB-INF/001.jpg");
//2 通过response获得输出字节流
OutputStream out = response.getOutputStream();
//3 两个对接
byte[] buffer = new byte[1024];
int len = 0;
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
out.flush();
}
in.close();
}
(7)使用字节流发送文件(文件下载)
告诉浏览器是什么东西:
response.setContentType(getServletContext().getMimeType(".jar"));
告诉浏览器推荐用户使用什么名称下载:
response.setHeader("Content-Disposition", "attachment;filename=ValidateCode.jar");
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//0 告诉浏览器是什么东西
//getServletContext().getMimeType(".jar") Context对象根据 后缀名去web.xml查找mime类型.
response.setContentType(getServletContext().getMimeType(".jar"));
//告诉浏览器推荐用户使用什么名称下载
response.setHeader("Content-Disposition", "attachment;filename=ValidateCode.jar");
//1 获得图片的输入流
InputStream in = getServletContext().getResourceAsStream("/WEB-INF/ValidateCode.jar");
//2 通过response获得输出字节流
OutputStream out = response.getOutputStream();
//3 两个对接
byte[] buffer = new byte[1024];
int len = 0;
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
out.flush();
}
in.close();
}
2 request对象
封装了浏览器发送来的请求信息.
(1)获取请求信息
请求首行
request.getMethod():GET
request.getRequestURI():/Day08-request/AServlet
request.getServletPath():/AServlet
request.getContextPath():/Day08-request
request.getScheme():http
请求头
//--原始方式获得请求头
StringgetHeader(String name)
longgetDateHeader(String name)
intgetIntHeader(String name)
EnumerationgetHeaders(String name)
EnumerationgetHeaderNames()
//---javaee封装好的方法.
request.getContentLength():-1
request.getContentType():null
request.getLocale():zh_CN
request.getQueryString():name=tom&age=18
request.getRequestURL():http://localhost:8080/Day08-request/AServlet
request.getRemoteAddr():0:0:0:0:0:0:0:1
request.getRemoteHost():0:0:0:0:0:0:0:1
request.getRemotePort():52074
request.getServerName():localhost
request.getServerPort():8080
请求空行
请求正文表单传送过来的键值对
(2)获得表单提交的参数.
1.GET
乱码:只要确保编码和解码一致,就绝对没有问题.
1.浏览器负责编码.浏览器使用的码表就是表单所在页面的码表.
默认使用ISO-8859-1解码.如下配置的URIEncoding来决定解码码表
URIEncoding="UTF-8"
connectionTimeout="20000"
redirectPort="8443"/>
如上配置会影响整个服务器不推荐.
我们使用如下代码解决:
//获得参数
String name = request.getParameter("name"); //ISO-8859-1进行解码
//因为服务器使用了错误的码表,那么我们按照错误的码表原路返回
byte[] nameByte = name.getBytes("ISO-8859-1"); //原路返回
//用正确的码表重新解码
String newName = new String(nameByte,"UTF-8"); //utf-8重新解码
System.out.println("解决之后的:"+newName);
2.POST
因为Post解码是在第一次调用getParameter之前,那么解决乱码只需要在调用该方法之前设置编码:
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
System.out.println(name);
涉及到获得表单参数的方法还有哪些呢?
getParameter 根据键获得值
getParameterMap() 获得服务器保存表单参数的容器. 就是map<String,String[]>. 泛型: habit=chi&habit=shui&habit=la
getParameterNames() 获得提交的所有键
String[ ] getParameterValues(String name) 根据键获得值. 获得一键对应多个值的情况的.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 Map getParameterMap() 获得服务器保存表单参数的容器. 就是map<String,String[]>. 泛型: habit=chi&habit=shui&habit=la
Map<String,String[]> map = request.getParameterMap();
for(Entry<String, String[]> en : map.entrySet()){
String key = en.getKey();
String[] value = en.getValue();
System.out.println(key+"==>" +Arrays.toString(value));
}
//2Enumeration getParameterNames() 获得提交的所有键
Enumeration<String> en = request.getParameterNames();
while(en.hasMoreElements()){
String key = en.nextElement();
System.out.println("提交上来的键==>"+key);
}
//3String[] getParameterValues(String name) 根据键获得值. 获得一键对应多个值的情况的.
String[] habits = request.getParameterValues("habit");
System.out.println(Arrays.toString(habits));
String habit = request.getParameter("habit");
System.out.println("getParameter获得多个值==>"+habit);
}
(3)request的请求转发功能.
转发:
一个Servlet处理完毕交给下面的servlet(JSP)继续处理.
作用:
在现实开发中,没有servlet转发给servlet的情况.都是由servlet转发给JSP.如登入的时候账号密码输入完毕后,跳转至正确与错误界面
这样可以达到分工的作用:
servlet:比较适合处理业务.
JSP:比较适合显示功能
注意问题:
//servlet中不要做输出正文的动作,没有结果的
//如果放到前面会出现乱码.
//但是响应头是可以设置的.
request.getRequestDispatcher("/login/success.jsp").forward(request, response);//从当前servlet转到如下jsp。
//1 获得表单提交的用户名密码
String name = request.getParameter("name");
String password = request.getParameter("password");
//2 判断是否正确 tom 1234 才算成功
if(name!=null && name.trim().length()>0 && name.equals("tom")&&
password!=null && password.trim().length()>0 && password.equals("1234")){
//成功 ==> 转发到成功页面
request.getRequestDispatcher("/login/success.jsp").forward(request, response);
//自己来做,很多弊端,不要这样
/* AServlet a = new AServlet();
a.service(request, response);*/
}else{
//失败 ==> 转发到失败页面
request.getRequestDispatcher("/login/error.jsp").forward(request, response);
}
(4)request的请求包含功能
包含:
jsp居多)共同向浏览器输出内容.
作用:
在现实开发中,多个页面含有相同的内容,我们把相同的内容抽取到一个jsp中,在需要显示这个段内容的jsp中,包含抽取的jsp.可以达到
统一管理相同的内容.
public class FServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("这是正文部分<hr>");
request.getRequestDispatcher("/GServlet").include(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().print("这是页脚部分");
}
(5)request域的应用.
原理:
在request对象中含有一个map.这个map就是request域.
作用:
在将来开发中. 使用请求转发时,servlet处理完数据, 处理结果要交给jsp显示. 可以使用request域将处理结果从servlet带给jsp显示.
操作:
1.setAttribute 存入一个键值对
2.getAttribute 通过键取出值
3.getAttributeNames获得域中所有键
4.removeAttribute跟据键移除一个键值对
request的范围:
一个request对象对应一个request域(map).
系统当前有多少个request就有多少request域.
public class HServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 获得表单提交的用户名密码
String name = request.getParameter("name");
String password = request.getParameter("password");
//
Map<String,String> error = new HashMap<String, String>();
//2 验证
if(!(name!=null && name.trim().length()>0 && name.equals("tom"))){
error.put("name", "用户名有误!");
}
if(!(password!=null && password.trim().length()>0 && password.equals("1234"))){
error.put("password", "密码错误!");
}
//将错误信息通过request域带到错误页面
request.setAttribute("error",error );
if(error.size() > 0){
//失败==> 回到登录页面,并显示错误信息
request.getRequestDispatcher("/login2/login.jsp").forward(request, response);
}else{
//成功==> 成功页面
request.getRequestDispatcher("/login2/success.jsp").forward(request, response);
}
}
}
<body>
<h1>用户登录</h1>
<form action="/Day08-request/HServlet" method="POST">
用户名:<input type="text" name="name" /> <br>
密码:<input type="password" name="password" /><br>
<input type="submit" >
</form>
<%
Map<String,String> error = (Map<String,String>)request.getAttribute("error");
if(error!=null && error.size()>0){
for(Entry<String,String> en : error.entrySet()){
out.print("<font color='red'>");
out.print(en.getValue()+"<br>");
out.print("</font>");
}
}
%>
</body>