[Java] 纯文本查看 复制代码
30 第五阶段WEB核心技术
30.1【HTTP协议的概述】
30.2【HTTP抓包】
30.3【HTTP请求响应详解】
Ø 请求部分
* 请求行
* 提交方式:
* 提交方式有很多,常用的GET和POST:
* GET和POST的区别:
* GET的提交的参数会显示到地址栏上,而POST不显示.
* GET往往是有大小限制的,而POST没有大小的限制.
* GET没有请求体,而POST有请求体.
* 提交路径:
* 协议版本:
* 请求头
* 都是键值对的形式显示的.一般一个key对应一个value,也有个别的是一个key对应多个value.
* User-Agent :代表浏览器的类型. --- 文件下载:下载中文文件:IE使用URLEncodor进行编码,而Firefox使用Base64编码.
* Referer :代表的是网页的来源. --- 防盗链.
* If-Modified-Since :通常与响应中的头Last-Modified一起使用查找本地缓存.
* 请求体
* 就是POST提交方式的提交的参数.
Ø 响应部分
* 响应行:
* 协议版本
* 状态码 :
* 200 :成功
* 302 :重定向
* 304 :查找本地缓存
* 404 :资源不存在
* 500 :服务器内部错误
* 状态码描述
* 响应头:键值对,一般一个key对应一个value,也有一个key对应多个value.
* Last-Modified :与请求中的If-Modified-Since一起使用查找本地缓存.
* Content-Dispostion :文件下载的使用使用的一个头信息.
* Location :重定向的跳转的路径.
* Refresh :定时刷新/定时跳转.
* 响应体:显示浏览器的页面的内容.
30.4【Servlet的概述】
servlet 就是运行在web服务器上的小的java程序,用来接收和响应客户端发来的请求.
30.4.1【使用ServletRequest接收参数】 234
* String getParameter(String name); ---用于接收一个名称对应一个值的数据.(文本框,单选框)
* String[] getParameterValues(String name);---用于接收一个名称对应多个值的数据.(复选框)
* Map getParameterMap(); ---用于接收表单中的所有的数据,Map的key是表单提交的参数名称,Map的value是提交参数的值.
* Enumeration getParameterNames() ---用于获取表单中提交的所有的参数的名称.(Enumeration 枚举类型
//这是一个servlet的代码案例
public class Servletdemo1 implements Servlet{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//解决res乱码问题
res.setContentType("text/html;charset=UTF-8");
res.getWriter().write("春天来了");
//post 乱码问题的解决办法
req.setCharacterEncoding("utf-8");
//获取单个参数
String name = req.getParameter("name");
//获取一个参数的数组(复选框)
String[] hobby = req.getParameterValues("hobby");
//获取一个参数的map集合
Map<String, String[]> maps = req.getParameterMap();
for (String key : maps.keySet()) {
String[] value = maps.get(key);
System.out.println(key+" "+Arrays.toString(value));
}
System.out.println(Arrays.toString(hobby));
System.out.println(name);
}
30.5 Servlet的生命周期:(*****) 237
这个是重点,一般面试时会问, 默认情况下servlet是在用户第一次请求的时候,服务器创建的一个servlet实例,然后servlet中的init方法就会执行,任何一次请求都会创建一个新的线程去访问servlet方法中的service的方法,在service方法内部会根据请求的方式不同调用不同的doXXX的方法,(例如get方式就是doGet()post方法就是doPost(方法))当服务器关闭或者项目被充服务器移除掉之后servlet实例就会被销毁,那么destory方法就会执行. 这就是servlet的生命周期.
30.5.1【启动时创建Servlet】 237
在web.xml中在<servlet></servlet>标签中配置:
* <load-on-startup>2</load-on-startup> --- 传入正整数,整数越小,被创建的优先级就越高.这句话要写在<servlet-class>标签的后面,不然会报错
30.5.2【url-pattern的配置】 237
url-pattern配置方式共有三种:
1.完全路径匹配 :以 / 开始 例如: /ServletDemo4 , /aaa/ServletDemo5 , /aaa/bbb/ServletDemo6
2.目录匹配 :以 / 开始 需要以 * 结束. 例如: /* ,/aaa/* ,/aaa/bbb/*
3.扩展名匹配 :不能以 / 开始 以 * 开始的. 例如: *.do , *.action
***** 错误的写法 : /*.do
有如下的配置:
<servlet>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.itheima.a_servlet.ServletDemo4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo4</servlet-name>
<url-pattern>/ServletDemo4</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ServletDemo5</servlet-name>
<servlet-class>com.itheima.a_servlet.ServletDemo5</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo5</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ServletDemo6</servlet-name>
<servlet-class>com.itheima.a_servlet.ServletDemo6</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo6</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
这里需要注意一下:路径如果有包含的关系的话, 完全路径匹配>目录匹配>扩展名匹配
30.6.2【使用ServletContext对象读取WEB项目下的文件】 246
* InputStream getResourceAsStream(String path); --- 根据提供路径读取文件返回一个文件的输入流. path = “/WEB-INF/classes/db.properties” 这个是服务器路径不需要写项目名,WEB-INF这个路径是对浏览器屏蔽的!在里面写的文件浏览器是访问不到的,因为里面放着是关键的jar包等,
* String getRealPath(String path); --- 返回一个路径的磁盘绝对路径.
得到了磁盘绝对路径后可以使用普通的文件输入流开始读取文件了
代码实现:
使用getResourceAsStream读取
/**
* 使用ServletContext中的getResourceAsStream读取.
* @throws FileNotFoundException
* @throws IOException
*/
private void test2() throws FileNotFoundException, IOException {
// 获得ServletContext:
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(is);
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClass);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
使用getRealPath读取文件:
/**
* 使用ServletContext中的getRealPath读取.
* @throws FileNotFoundException
* @throws IOException
*/
private void test3() throws FileNotFoundException, IOException {
// 获得ServletContext:
ServletContext context = this.getServletContext();
String realPath = context.getRealPath("/WEB-INF/classes/db.properties");
// 获得该文件的磁盘绝对路径.
System.out.println(realPath);
InputStream is = new FileInputStream(realPath);
Properties properties = new Properties();
properties.load(is);
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClass);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
30.6.3ServletContext的功能: 247
【功能一:读取全局初始化参数】
在web.xml配置全局初始化参数:
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123</param-value>
</context-param>
代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = this.getServletContext().getInitParameter("username");
String password = this.getServletContext().getInitParameter("password");
System.out.println(username+" "+password);
Enumeration<String> e = this.getServletContext().getInitParameterNames();
while(e.hasMoreElements()){
String name = e.nextElement();
String value = this.getServletContext().getInitParameter(name);
System.out.println(name+" "+value);
}
}
【功能二:获得文件的MIME的类型】
* 获得文件的MIME的类型.
代码实现:
/**
* 获得文件的MIME的类型
*/
private void test2() {
String type = this.getServletContext().getMimeType("1.html");
System.out.println(type);
}
【功能三:作为域对象存取数据】
范围:整个web项目.而且全局的对象.
创建:服务器启动的时候,服务器为每个web项目创建一个单独的ServletContext对象.
销毁:服务器关闭的时候销毁ServletContext.
【功能四:读取web项目下的文件】
30.6.5【Response的概述】 249
Ø Response:代表响应的对象.从服务器向浏览器输出内容.
【Response的常用的API】在api中查找HttpServletResponse
部分api
void setStatus(int sc) 设置状态码
ServletOutputStream getOutputStream() 获得输出流
void setHeader(String name,String value) 设置头信息
30.6.6中文文件的下载: 251
//首先在页面点击文件的时候传递过来文件名称
//由于中文会有乱码问题,servlet的request的缓冲区是ISO-8859-1编码,而现实的时候需要用到的是UTF-8编码,所以要将传过来的数据用iso-8859-1转成二进制字节,然后根据utf-8转成字符串,就可以得到中文了
//然后文件下载要设置两个头一个流
//setHead("Content-Type",文件类型);
//setHead("Content-Disposition","attachment;filename="+文件的非中文名);//这里的非中文名是根据不同的浏览器编码将文件名进行编码的(因为头信息是不能有中文的,所以这个地方要进行编码的)
//然后获得一个文件的输入流再获得文件的输出流
以下是代码实例:
Ø IE浏览器下载中文文件的时候采用的URL的编码. URLEncoser
Ø Firefox浏览器下载中文文件的时候采用的是Base64的编码. Base64
/**
* 文件下载的Servlet
*/
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收参数
String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8");
System.out.println(filename);
// 2.完成文件下载:
// 2.1设置Content-Type头
String type = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type", type);
// 2.3设置文件的InputStream.
String realPath = this.getServletContext().getRealPath("/download/"+filename);
// 根据浏览器的类型处理中文文件的乱码问题:
String agent = request.getHeader("User-Agent");
System.out.println(agent);
if(agent.contains("Firefox")){
filename = base64EncodeFileName(filename);
}else{
filename = URLEncoder.encode(filename,"UTF-8");
}
// 2.2设置Content-Disposition头
response.setHeader("Content-Disposition", "attachment;filename="+filename);
InputStream is = new FileInputStream(realPath);
// 获得response的输出流:
OutputStream os = response.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
}
public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?"
+ new String(base64Encoder.encode(fileName
.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
30.6.7response输出响应内容的方法: 253
* 输出中文乱码的处理:
* 字节流:
* 设置浏览器默认打开的编码:
* resposne.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
* 设置中文字节取出的时候编码.
* “中文”.getBytes(“UTF-8”);
* 字符流:
* 设置浏览器打开的时候的编码
* resposne.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
* 设置response的缓冲区的编码
* response.setCharacterEncoding(“UTF-8”);
***** 简化的写法:response.setContentType(“text/html;charset=UTF-8”);
30.7.1【Request的API】 254
常用的api
功能一:获得客户机相关的信息
String getMethod() 获得请求方式
String getRequestURL() 获得请求路径 Ø URL获得是全路径,就是http://一直往后
StringBuffer getRequestURI() 获得请求路径Ø URI获得是从工程名往后的路径
String getRemoteAddr() 获得客户机相关信息
String getContextPath() 获得工程名
功能二:获得从页面中提交的参数:
String getParameter(String name)
Map getParameterMap()
Enumeration getParameterNames()
String[] getParameterValues(String name)
功能三:作为域对象存取数据:
void removeAttribute(String name)
void setAttribute(String name,Object o)
Object getAttribute(String name)
30.7.2处理request接收参数的中文乱码的问题: 256
Ø POST的解决方案:
* POST的参数在请求体中,直接到达后台的Servlet.数据封装到Servlet中的request中.request也有一个缓冲区.request的缓冲区也是ISO-8859-1编码.
* 设置request的缓冲区的编码:
* request.setCharacterEncoding(“UTF-8”); --- 一定要在接收参数之前设置编码就OK.
代码:
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
Ø GET的解决方案:
* 1.修改tomcat的字符集的编码.(不推荐)
* 2.使用URLEncoder和URLDecoder进行编码和解码的操作.
* 3.使用String的构造方法:
代码:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");
30.7.3Request作为域对象存取数据: 256
使用request对象存取数据:
setAttribute(String name,String value);
Object getAttribute(String name);
作用范围就是一次请求的范围.
创建和销毁:
* 创建:客户端向服务器发送了一次请求以后,服务器就会创建一个request的对象.
* 销毁:当服务器对这次请求作出了响应之后.
30.7.4重定向和转发的区别:(redirect和forward的区别) 257
重定向是两次请求两次响应,转发是一次请求一次响应
重定向的地址栏会发生变化,转发的地址栏不变
重定向的路径要加上工程名,转发的路径不需要加工程名
重定向可以跳转到任意的网站,转发只能在服务器内部进行转发
实例:
重定向:
response.setStatus(302);
response.setHeader("location","/工程名/路径");
简写 request.sendRedirect("/工程名/路径");
转发:request.getRequestDispatcher("/路径").forword(request,response);
30.8 Cookie&Session 257
Cookie :将数据保存到客户端端浏览器
Ø 向浏览器保存数据:
HttpServletResponse有一个方法:
* void addCookie(Cookie cookie);
Ø 获得浏览器带过来的Cookie:
HttpServletRequest有一个方法:
* Cookie[] getCookies();
Ø 创建一个Cookie对象:
* Cookie(String name,String value);
Session :将数据保存到服务器端
30.8.2Cookie的常用API: 260
*getName();
*getValue();
*setDomain(String domain); --设置Cookie有效域名
*setpath(String path); --设置Cookie的有效路径 设置后只有匹配的路径才能传过去cookie
*setMaxAge(int maxAge); --设置Cookie的有效时间.
Cookie的分类:
会话级别的Cookie:默认的cookie 关闭浏览器Cookie就会销毁.
持久级别的cookie:可以设置Cookie的有效时间,那么关闭浏览器Cookie还会存在.手动销毁持久性Cookie, setMaxAge(0)--前提是路径必须一致
销毁步骤:1创建一个和原来cookie名字一样的cookie
2设置cookie与原来cookie一致的有效路径
3设置cookie的有效时间为0
4回写到浏览器.