其余更多java基础文章: java基础学习(目录)html
学习request和response以前先学习一下http请求java
浏览器向服务器请求某个web资源时,称之为浏览器向服务器发送了一个http请求。一个完整http请求应该包含三个部分:web
请求行:GET /java.html HTTP/1.1 请求行中的GET称之为请求方式,
请求方式有:POST,GET,HEAD,OPTIONS,DELETE,TRACE,PUT。
经常使用的有:POST,GET
通常来讲,当咱们点击超连接,经过地址栏访问都是get请求方式。经过表单提交的数据通常是post方式。
能够简单理解GET方式用来查询数据,POST方式用来提交数据,get的提交速度比post快
GET方式:在URL地址后附带的参数是有限制的,其数据容量一般不能超过1K。
POST方式:能够在请求的实体内容中向服务器发送数据,传送的数据量无限制。apache
一个HTTP响应表明着服务器向浏览器回送数据,一个完整的HTTP响应应该包含四个部分:编程
格式: HTTP版本号 状态码 缘由叙述 状态行:HTTP/1.1 200 OK 状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类json
HttpServletRequest对象表明客户端的请求,当客户端经过HTTP协议访问服务器时,HTTP请求头中的全部信息都封装在这个对象中,开发人员经过这个对象的方法,能够得到客户这些信息。 request就是将请求文本封装而成的对象,因此经过request能得到请求文本中的全部内容,请求头、请求体、请求行 数组
咱们能够查看任意一个网页,它都是有请求头的。浏览器
相关方法:
String getHeader(String name) 根据头名称获得头信息值
long getDateHeader(java.lang.String name) 得到指定头内容Date
int getIntHeader(java.lang.String name) 得到指定头内容int
Enumeration getHeaderNames() 获得全部头信息name
Enumeration getHeaders(String name) 根据头名称获得相同名称头信息值缓存
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String key = (String)headerNames.nextElement();
String value = req.getHeader(key);
System.out.println(key+"="+value);
}
复制代码
1)与表单获取相关的方法:
String getParameter(name) :根据表单中name属性的名,获取value属性的值方法
String[] getParameterValues(String name):专为复选框取取提供的方法
getParameterNames():获得表单提交的全部name的方法
Map<String , String[]> getParameterMap(): 获得表单提交的全部值的方法 //作框架用,很是实用
getInputStream: 以字节流的方式获得全部表单数据tomcat
2)与操做非表单数据相关的方法(request也是一个域对象):
void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);
3)与请求转发相关的方法:
RequestDispatcher getRequestDispatcher(String path) //获得请求转发或请求包含的协助对象
forward(ServletRequest request, ServletResponse response) //转发的方法
include(ServletRequest request, ServletResponse response) //请求包含
4)与编码相关的方法:
//解决post方式编码
request.setCharacterEncoding("UTF-8") :告诉服务器客户端什么编码,只能处理post请求方式
//解决get方式编码
String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);
#####3. 其余经常使用请求方法
getMethod();
getRequestURL();
getRequestURI();
getServerName();
getServerPort();
getContextPath();
getServletPath();
getQueryString();
getRemoteAddr();
getProtocol();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.统一资源标记符 /Web_Servlet/ServletTest3
String uri = req.getRequestURI();
System.out.println(uri);
//2.统一资源定位符 http://localhost:6060/Web_Servlet/ServletTest3
StringBuffer url = req.getRequestURL();
System.out.println(url);
//3.协议和版本 HTTP/1.1
String potocol = req.getProtocol();
System.out.println(potocol);
//4.协议 http
String scheme = req.getScheme();
System.out.println(scheme);
//5.主机(域名) localhost,若是你使用的是ip地址,就显示ip地址
String serverName = req.getServerName();
System.out.println(serverName);
//6.端口 6060(这是我本身修改了的端口,默认是8080)
int port = req. getServerPort();
System.out.println(port);
//7.发布到tomcat下的项目名称 /Web_Servlet
String contextPath = req.getContextPath();
System.out.println(contextPath);
//8.servlet路径 /ServletTest3
String servletPath = req.getServletPath();
System.out.println(servletPath);
//9.获取全部请求参数,即?以后全部东西。 username=faker&password=mid
String queryString = req.getQueryString();
System.out.println(queryString);
//10.远程主机的ip地址 0:0:0:0:0:0:0:1
String remoteAddr = req.getRemoteAddr();
System.out.println(remoteAddr);
}
复制代码
Web服务器收到客户端的http请求,会针对每一次请求,分别建立一个用于表明请求的request对象、和表明响应的response对象。request和response对象即然表明请求和响应,那咱们要获取客户机提交过来的数据,只须要找request对象就好了。要向容器输出数据,只须要找response对象就好了。
HttpServletResponse对象表明服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。
setStatus(int sc) 设置响应状态码
setHeader(String name, String value) 设置响应头信息
getWrite(); 字符输出流
getOutputStream(); 字节输出流
setCharacterEncoding(String charset) 告知服务器使用什么编码
setContentType(String type) 告诉响应的内容类型(text/html,application/json等)
response.sendRedirect(path);
注意:重定向没有任何局限,能够重定向web项目内的任何路径,也能够访问别的web项目中的路径,而且这里就用"/"区分开来,若是path使用了"/"开头,就说明我要从新开始定位了,不访问刚才的web项目,本身写项目名,若是path没有使用"/"开始,那么就知道是访问刚才那个web项目下的servlet,就能够省略项目名了。就是这样来区别。
request.setCharacterEncoding()指定后能够经过getParameter()则直接得到正确的字符串,若是不指定,则默认使用iso8859-1编码。值得注意的是在执行setCharacterEncoding()以前,不能执行任何getParameter()。并且,该指定只对POST方法有效,对GET方法无效。
分析缘由,应该是在执行第一个getParameter()的时候,Java将会按照编码分析全部的提交内容,然后续的getParameter()再也不进行分析,因此setCharacterEncoding()无效。而对于GET方法提交表单是,提交的内容在URL中,一开始就已经按照编码分析提交内容,setCharacterEncoding()天然就无效。
response.setCharacterEncoding设置HTTP 响应的编码,若是以前使用response.setContentType设置了编码格式,则使用response.setCharacterEncoding指定的编码格式覆盖以前的设置.与response.setContentType相同的是,调用此方法,必须在getWriter执行以前或者response被提交以前
转发是发生在服务器的:
转发是由服务器进行跳转的,细心的朋友会发现,在转发的时候,浏览器的地址栏是没有发生变化的,在我访问Servlet111的时候,即便跳转到了Servlet222的页面,浏览器的地址仍是Servlet111的。也就是说浏览器是不知道该跳转的动做,转发是对浏览器透明的。经过上面的转发时序图咱们也能够发现,实现转发只是一次的http请求,一次转发中request和response对象都是同一个。这也解释了,为何可使用request做为域对象进行Servlet之间的通信。
重定向是发生在浏览器的:
重定向是由浏览器进行跳转的,进行重定向跳转的时候,浏览器的地址会发生变化的。曾经介绍过:实现重定向的原理是由response的状态码和Location头组合而实现的。这是由浏览器进行的页面跳转实现重定向会发出两个http请求,request域对象是无效的,由于它不是同一个request对象
不少人都搞不清楚转发和重定向的时候,资源地址究竟怎么写。有的时候要把应用名写上,有的时候不用把应用名写上。很容易把人搞晕。记住一个原则:给服务器用的直接从资源名开始写,给浏览器用的要把应用名写上
request.getRequestDispatcher("/资源名 URI").forward(request,response)
转发时"/"表明的是本应用程序的根目录
response.send("/web应用/资源名 URI");
重定向时"/"表明的是webapps目录
转发是服务器跳转只能去往当前web应用的资源
重定向是服务器跳转,能够去往任何的资源
转发的request对象能够传递各类类型的数据,包括对象
重定向只能传递字符串
转发时:执行到跳转语句时就会马上跳转
重定向:整个页面执行完以后才执行跳转
PrintWriter对象输出字符文本内容时,它内部仍是将字符串转换成了某种字符集编码的字节数组后再进行输出,使用PrintWriter对象的好处就是不用编程人员本身来完成字符串到字节数组的转换。
使用ServletOutputStream对象也能输出内容全为文本字符的网页文档,可是,若是网页文档内容是在Servlet程序内部使用文本字符串动态拼凑和建立出来的,则须要先将字符文本转换成字节数组后输出。
getOutputStream方法用于返回Servlet引擎建立的字节输出流对象,Servlet程序能够按字节形式输出响应正文。
getWriter方法用于返回Servlet引擎建立的字符输出流对象,Servlet程序能够按字符形式输出响应正文。
getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另外一方法。
getOutputStream方法返回的字节输出流对象的类型为ServletOutputStream,它能够直接输出字节数组中的二进制数据。
getWriter方法将Servlet引擎的数据缓冲区包装成PrintWriter类型的字符输出流对象后返回,PrintWriter对象能够直接输出字符文本内容。
Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎获取,Servlet引擎将这些数据看成响应消息的正文,而后再与响应状态行和各响应头组合后输出到客户端。
Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,若是没有,Servlet引擎将调用close方法关闭该输出流对象。
getOutputStream解决办法:
rgetWriter解决办法:
response. setContentType(“text/html;charset=UTF-8”);
//经过路径获得一个输入流
String path = this.getServletContext().getRealPath(filepath);
FileInputStream fis = new FileInputStream(path);
//建立字节输出流
ServletOutputStream sos = response.getOutputStream();
//获得要下载的文件名
String filename = path.substring(path.lastIndexOf("\\")+1);
//设置文件名的编码
filename = URLEncoder.encode(filename, "UTF-8");//将不安全的文件名改成UTF-8格式
//告知客户端要下载文件
response.setHeader("content-disposition", "attachment;filename="+filename);
response.setHeader("content-type", "image/jpeg");
//执行输出操做
int len = 1;
byte[] b = new byte[1024];
while((len=fis.read(b))!=-1){
sos.write(b,0,len);
}
sos.close();
fis.close();
复制代码
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("3秒后跳转页面.....");
//三秒后跳转到index.jsp页面去
response.setHeader("Refresh", "3;url='/index.jsp'");
复制代码
//浏览器有三消息头设置缓存,为了兼容性!将三个消息头都设置了
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma", "no-cache");
复制代码
//建立GZIPOutputStream对象,给予它ByteArrayOutputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
//GZIP对数据压缩,GZIP写入的数据是保存在byteArrayOutputStream上的
gzipOutputStream.write("asdfzxcvasdfzxvasdfzxcv".getBytes());
//gzipOutputStream有缓冲,把缓冲清了,并顺便关闭流
gzipOutputStream.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
//告诉浏览器这是gzip压缩的数据
response.setHeader("Content-Encoding","gzip");
//将压缩的数据写给浏览器
response.getOutputStream().write(bytes);
复制代码
//获取到网页是从哪里来的
String referer = request.getHeader("Referer");
复制代码