人生下来不是为了拖着锁链,而是为了展开双翼。 —— 雨果
Response对象,用于生成http响应信息. 对于开发人员来讲,就是 向response 对象中添加信息即可.
HTTP/1.1 200 OK
void setStatus(int sc)
void setStatus(int sc, String sm) Deprecated(过时)
void sendError(int sc)
void sendError(int sc, String msg)
键:值
void setHeader(String name, String value) 设置键值对.
void setDateHeader(String name, long date) 设置键值对.
void setIntHeader(String name, int value) 设置键值对.
void addHeader(String name, String value) 添加键值对.
void addDateHeader(String name, long date)添加键值对.
void addIntHeader(String name, int value) 添加键值对.
需要给浏览器的资源
getWriter(); 字符流.
getOutputStream() 字节流
使用Response发送错误信息
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendError(404,"找到也不告诉你!");
}
}
跳转
public class BServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//添加响应头=> Refresh
response.addHeader("Refresh", "3;url=http://localhost:8080");
// 让页面有倒计时的效果
response.getWriter().write("您将在3秒后跳转!" +
"");
}
}
重定向
public class CServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*//1 添加302状态码 => 告诉浏览器需要重定向
response.setStatus(302);
//2 添加Location响应头 => 高速浏览器重定向到哪里
response.setHeader("Location", "http://localhost:8080");*/
//该方法是对上面两行代码的封装
response.sendRedirect("http://localhost:8080");
}
}
解决浏览器端的乱码问题
public class DServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//控制解码码表
response.setHeader("Content-Type", "text/html;charset=GBK");
//控制编码码表
response.getOutputStream().write("黑马".getBytes("GBK"));
}
}
public class EServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//2 设置解码码表 => 与setContentType效果一样,自动查找设置的码表,将解码码表设置一致
response.setHeader("Content-Type", "text/html;charset=GBK");
//1 设置编码码表
//response.setCharacterEncoding("GBK");
//可以使用19行代替17行的代码.同时setContentType方法如果发现你填写码表,那么会同时自动设置编码码表
//response.setContentType("text/html;charset=GBK");
//3 输出
response.getWriter().write("黑马");
//结论:
//1 输出中文建议使用字符流
//2 解决字符流乱码 使用setContentType放可以同时设置编码解码两端的码表.
//3 注意: 码表的设置一定放到输出之前
//4 注意: 字符流与字节流不能同时使用
}
}
public class FServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//判断是否有查看的权限
// 1 获得图片的输入流
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/xxx1.jpg");
// 2 获得输出到浏览器的输出流
OutputStream os = response.getOutputStream();
// 3 两个流对接
byte[] buffer = new byte[1024];
int len = -1;
while((len = is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
}
}
传送文件
public class GServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//0 原则: 凡是响应正文中需要输出内容, 一定要设置content-type头
ServletContext sc = getServletContext();
String type = sc.getMimeType("abc.exe");
response.setContentType(type);
//0 设置响应头=> 提示用户保存名称 => Http协议不支持中文码表=> %E5%C3 => URLEncoder.encode("apache-汤姆-6.0.35.exe","UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode("apache-汤姆-6.0.35.exe","UTF-8"));
// 1 获得文件的输入流
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/apache-tomcat-6.0.35.exe");
// 2 获得输出到浏览器的输出流
OutputStream os = response.getOutputStream();
// 3 两个流对接
byte[] buffer = new byte[1024];
int len = -1;
while((len = is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
}
}
Request对象的方法
Request
HTTP请求协议:
请求首行 请求方式 请求路径 协议/版本号
String getMethod() 获得请求方式
request.getContextPath(): /day08-request 获得项目路径
String getServletPath()
request.getQueryString(): name=tom?age=19 获得请求路径中的参数
request.getRequestURI(): /day08-request/AServlet 获得当前访问的相对路径,相对主机路径
request.getRequestURL(): http://localhost:8080/day08-request/AServlet 获得当前访问的绝对路径
request.getServletPath(): /AServlet 获得servlet路径
String getScheme() 获得协议协议
请求头 键:值
request.getContentLength(): -1 返回正文内容长度
request.getContentType(): null 返回正文内容类型
request.getLocale(): zh_HANS_CN 获得accept-language:zh_CN
request.getServerName(): localhost 获得主机名称
request.getServerPort(): 8080 获得访问端口号
String getHeader(String name) 根据键获得值(值只有一个)
long getDateHeader(String name)
int getIntHeader(String name)
Enumeration getHeaderNames() 获得所有请求头的名字
Enumeration getHeaders(String name) 根据键获得值(值有多个)
请求空行
请求正文 post请求才有=> 请求参数 => name=tom&age=18
String getParameter(String name) 根据参数键获得参数值
Map<String,String[]> getParameterMap() 返回封装参数的Map
Enumeration getParameterNames() 获得所有参数的键
String[] getParameterValues(String name) 根据参数键获得参数值(值有多个)
网络编程
request.getRemoteAddr(): 192.168.13.102
request.getRemoteHost(): 192.168.13.102
request.getRemotePort(): 53479
取出所有的参数
public class BServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1 获得 所有参数的键
Enumeration en = request.getParameterNames();
// 2 遍历所有键
while(en.hasMoreElements()){
String key = en.nextElement();
//根据键 获得值
String value = request.getParameter(key);
System.out.println(key+"==>"+value);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1 获得 所有参数的键
Enumeration en = req.getParameterNames();
// 2 遍历所有键
while(en.hasMoreElements()){
String key = en.nextElement();
//根据键 获得值
String value = req.getParameter(key);
System.out.println(key+"==>"+value);
}
}
}
解决乱码问题
public class CServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
System.out.println(name);
//1 将乱码使用latin码表 编码回字节数组
byte[] bytes= name.getBytes("ISO-8859-1");
//2 将字节用UTF-8码表 解码回中文
String name2 = new String(bytes, "UTF-8");
System.out.println(name2);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp)
throws ServletException, IOException {
//post解决乱码,只要在调用获得参数方法前.设置解码码表即可
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
System.out.println(name);
}
}
![这里写图片描述](http://img.blog.csdn.net/20160918214841183)
转发逻辑
在DServlet中处理逻辑,在JSP中现实给浏览器
public class DServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("我来处理业务逻辑");
String name = "肉丝";//假设该值是从数据库中取出来.要将该值交给EServlet显示
//将name变量放入request域
request.setAttribute("name", name);
//转发(山寨,帮助我们理解转发原理)
/*EServlet eservlet = new EServlet();
eservlet.service(request, response);*/
response.getWriter().write("DServlet hello!");
//转发
request.getRequestDispatcher("/EServlet").forward(request, response);
}
}
public class EServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("我来负责输出显示!");
String name = (String) request.getAttribute("name");
System.out.println("EServlet:"+name);
response.getWriter().write("EServlet hello!");
}
}
public class FServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("这是第一部分!
");
//包含
request.getRequestDispatcher("/GServlet").include(request, response);
response.getWriter().write("这是第二部分!
");
}
}
public class GServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().write("这是相同的部分!
");
}
}
请求转发/请求包含
请求转发:
一个servlet里面处理逻辑, 将处理结果交给下一个Servlet(JSP)负责显示.
操作(代码):
request.getRequestDispatcher(“/EServlet”).forward(request,response);
问题: 将转发与重定向做对比,有什么异同?
1.浏览器一共发送了几个请求?
重定向: 两次请求
转发: 一次请求
2.浏览器的地址发生变化吗?
重定向: 会发生变化
转发: 不会发生变化
3.会改变请求方式吗?
重定向: 未必.重定向的第2次请求一定是get.
转发: 不会.
4.request域可不可以共享数据?
重定向: 不可以,因为会产生两个request对象.
转发: 可以. 因为是在一个请求范围内.使用的是同一个request对象.
注意:
servlet 向 jsp转发. servlet专注于逻辑处理。 JSP专注于显示处理结果。 不要在应该处理逻辑的地方做显示操作。也就是说在servlet中
不要使用字符流或字节流做任何输出的动作(不能添加响应正文)。 可以添加响应头。
转发的Servlet不可以向response的正文中添加任何内容.但是可以向响应头添加内容.
//——————————————————————————————————————————————
请求包含
一般请求包含不会在两个servlet中进行.都是在两个jsp中进行.
当在多个页面总有需要重复显示的内容. 我们可以把这段内容封装到一个jsp中. 以后凡是要显示这段重复的内容时,只需要把封装的jsp包含进来即可.
操作(代码):
request.getRequestDispatcher(“/XXX”).include(request,response);
//—————————————————————————————————-
Request域
request域就是一个放在request对象中的map.
request域范围:
与request对象的声明周期是一样的. 请求到达服务器时,request对象创建, 当服务器响应浏览器之后, request对象销毁.
request域通常在请求转发时使用, servlet处理结果,将结果放置到request域中,带给jsp显示.
setAttribute(key,value)
getAttribute(key)
removeAttribute(key)
getAttributeNames()
//——————————————————————————————————
什么时候用转发?
servlet负责处理逻辑, jsp用于显示. 需要共享数据,一定要使用转发. 使用重定向会使数据丢失.
什么时候用重定向?
1. 当需要跳转到站内,并且地址栏要求发生变化时,使用重定向.前提是不需要共享数据.
2. 当需要跳转到站外时,一定只能使用重定向.