ServletContext的功能:
【功能一:读取全局初始化参数】
配置全局初始化参数:
<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项目下的文件】
【演示传统方式读取WEB工程文件】
/**
* 传统方式读取文件:
* * 使用的是相对路径,相对的JVM的路径.
* * 但是现在是一个web项目,相对于JVM的路径的.现在JVM已经交给tomcat管理.
* @throws FileNotFoundException
* @throws IOException
*/
private void test1() throws FileNotFoundException, IOException {
InputStream is = new FileInputStream("src/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);
}
【使用ServletContext对象读取WEB项目下的文件】
* InputStream getResourceAsStream(String path); --- 根据提供路径读取文件返回一个文件的输入流.
* 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);
}
类加载器读取文件:(扩展)
public static void readFile() throws IOException{
// 使用类的加载器来读取文件.
// 类的加载器用来加载class文件,将class文件加载到内存.
InputStream is = ReadFileUtils.class.getClassLoader().getResourceAsStream("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);
}
【Response的概述】
Response:代表响应的对象.从服务器向浏览器输出内容.
【Response的常用的API】
Ø 响应行:
* 设置状态码.
Ø 响应头:
* 针对一个key对应多个value的头信息.
* 针对一个key对应一个value的头信息.
Ø 响应体
【文件下载的方式】
Ø 一种:超链接下载.直接将文件的路径写到超链接的href中.---前提:文件类型,浏览器不支持.
Ø 二种:手动编写代码的方式完成文件的下载.
* 设置两个头和一个流:
* Content-Type:文件的MIME的类型.
* Content-Disposition:以下载的形式打开文件.
* InputStream:文件的输入流.
案例:登录成功后,完成文件的下载.
需求:
在登录成功后,页面跳转到文件下载的列表的页面,点击列表中的某些链接,下载文件.
步骤一:将之前的登录功能准备好:
步骤二:在文件下载列表页面上添加文件下载的链接:
步骤三:完成文件下载的代码的实现:
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收参数
String filename = request.getParameter("filename");
// 2.完成文件下载:
// 2.1设置Content-Type头
String type = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type", type);
// 2.2设置Content-Disposition头
response.setHeader("Content-Disposition", "attachment;filename="+filename);
// 2.3设置文件的InputStream.
String realPath = this.getServletContext().getRealPath("/download/"+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();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
中文文件的下载:
IE浏览器下载中文文件的时候采用的URL的编码.
Firefox浏览器下载中文文件的时候采用的是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-Ty
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);
}
}
respo
response输出响应内容的方法:
向页面响应的方法:
* getOutputStream();
* getWriter();
工程的根路径
* 这两个方法是互斥的.
* 做出响应的时候只能使用其中的一种流响应.
* 输出中文乱码的处理:
* 字节流:
* 设置浏览器默认打开的编码:
* 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”);
让我们的内容和浏览器的编码一致.
【Request的概述】
Ø Request代表用户的请求.
【Request的API】
功能一:获得客户机相关的信息
Ø 获得请求方式:
Ø 获得请求的路径:
Ø 获得客户机相关的信息:
Ø 获得工程名:
功能二:获得从页面中提交的参数:
功能三:作为域对象存取数据:
【演示request获得客户机的信息】
public class RequestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获得请求方式:
String method = request.getMethod();
System.out.println("请求方式:"+method);
// 获得客户机的IP地址:
String ip = request.getRemoteAddr();
System.out.println("IP地址:"+ip);
// 获得用户的请求的路径:
String url = request.getRequestURL().toString();
String uri = request.getRequestURI();
System.out.println("获得请求的URL:"+url);
System.out.println("获得请求的URI:"+uri);
// 获得发布的工程名:
String contextPath = request.getContextPath();
System.out.println("工程名:"+contextPath);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1.1.1.1 处理request接收参数的中文乱码的问题:
现在无论是GET还是POST提交中文的时候,都会出现乱码的问题.
解决:
Ø POST的解决方案:
* POST的参数在请求体中,直接到达后台的Servlet.数据封装到Servlet中的request中.request也有一个缓冲区.request的缓冲区也是ISO-8859-1编码.
* 设置request的缓冲区的编码:
* request.setCharacterEncoding(“UTF-8”); --- 一定要在接收参数之前设置编码就OK.
Ø GET的解决方案:
* 1.修改tomcat的字符集的编码.(不推荐)
* 2.使用URLEncoder和URLDecoder进行编码和解码的操作.
* 3.使用String的构造方法:
Request作为域对象存取数据:
使用request对象存取数据:
* setAttribute(String name,String value);
* Object getAttribute(String name);
request的作用范围:
* 作用范围就是一次请求的范围.
* 创建和销毁:
* 创建:客户端向服务器发送了一次请求以后,服务器就会创建一个request的对象.
* 销毁:当服务器对这次请求作出了响应之后.
重定向和转发的区别:(redirect和forward的区别)
* 1.重定向的地址栏会发生变化,转发的地址栏不变.
* 2.重定向两次请求两次响应,转发一次请求一次响应.
* 3.重定向路径需要加工程名,转发的路径不需要加工程名.
* 4.重定向可以跳转到任意网站,转发只能在服务器内部进行转发.
-----------------------------------------------------------------------------
01_响应对象的概述&向客户端发送数据
WEB服务器会针对每一个客户端发出的HTTP请求,分别的创建一个请求对象和一个响应对象
如果需要获取客户端提交的数据,需要使用请求对象
如果需要向客户端发送一些数据,需要使用响应对象
响应 : 响应行 响应头 响应正文
1XX:浏览器发送的请求信息不完善,需要浏览器进一步补充资料
2XX:响应正常完成
3XX:本次请求已经完成,但是需要浏览器进行进一步操作 302
4XX:请求的资源错误
5XX:服务器端错误
注意:
这两个流互相排斥,在一个Servlet中只能使用其中的一个,如果有字符输出流则不能有字节输出流,否则会出现异常
02_字节流向客户端发送中文的乱码处理
编码:
二进制 A 65 a 97 汉字
ASCII 美国标准信息码(128字符)
ISO-8859-1 -16 一共有15编码 13
//GB2312 2个字节表示一个字符 6700+
GBK 2个字节表示一个字符 18000+ 国家强制标准
Unicode 万国码 2个字节表示一个字符
UTF-8 用1-6个字节来表示一个字符
ANSI 本地平台默认
中文版window GBK
英文版的window UTF-8
原因:
乱码的出现是因为前后编码不一致,发送数据的编码,接收数据的编码
服务器发送数据:ISO-8859-1
浏览器接收数据:GBK
解决方法一:
将服务器发送数据格式改为GBK
OutputStream os = response.getOutputStream();
os.write("定个小目标".getBytes());//默认GBK
解决方法二
//设置响应头,告诉浏览器你应该使用什么编码
response.setHeader("Content-type", "text/html;charset=UTF-8");
os.write("定个小目标".getBytes("UTF-8"))
03_字符流向客户端发送中文的乱码处理
原因
服务器发送数据:ISO-8859-1 -> GBK
浏览器接收数据:GBK
解决方法一:
response.setCharacterEncoding("GBK");//设置编码的格式,也就是设置服务器发送数据的格式
如果服务器发送的是UTF-8
response.setCharacterEncoding("UTF-8");//服务器
response.setContentType("text/html;charset=UTF-8");//告诉浏览器采用什么方式进行解码
推荐方案
response.setContentType("text/html;charset=UTF-8");//告诉浏览器采用什么方式进行解码
04_响应头Refresh
定时自动刷新
response.setHeader("Refresh", "3");
定时自动跳转
response.setHeader("Refresh", "3;URL=http://baidu.com"); //跳转外部资源
response.setHeader("Refresh", "3;URL=/myResponse/ResponseDemo");//跳转内部资源
转发和跳转的区别
转发:共享请求和响应对象,跳转:不共享
转发:只能是内部地址,跳转:内部地址和外部地址都可以
转发:地址栏不会发生变化,跳转:地址栏会发生变化
05_请求重定向
概念:一个WEB资源接收到客户端的请求之后,通知这个客户端去访问(请求)另外的一个WEB资源
重定向和转发的区别
请求次数
重定向发出两次请求
转发只发出一次请求,共享请求对象和响应对象
访问的路径
重定向可以访问内部的路径,也可以访问外部的路径
转发只能访问内部的路径
地址栏
重定向的地址栏发生变化
转发地址栏不会变化
原理:设置location响应头,同时还需要设置一个响应码(状态码),302/307
response.setHeader("Location", "http://baidu.com");
response.setStatus(307); //立即重定向
06_文件下载案例
步骤
//设置响应头
response.setHeader("Content-disposition", "attachment;filename=pic01.jpg");
//获取字节输出流对象
OutputStream os = response.getOutputStream();
//创建字节输入流对象
String path = getServletContext().getRealPath("/WEB-INF/pic01.jpg");
FileInputStream fis = new FileInputStream(path);
//循环读取并向客户端发送数据
int len = 0;
byte[] bys = new byte[1024];
while((len = fis.read(bys)) != -1) {
//向客户端发送数据
os.write(bys,0,len);
}
//释放资源
fis.close();
07_文件下载的细节
注意:
响应头里不能有中文,中文被认为是不安全的字符
更改如下:
String s = URLEncoder.encode("定个大目标.jpg", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + s);
08_请求对象的概述&获取请求行
HttpServletRequest
请求对象封装了HTTP协议的请求行,请求头,请求体,我们可以通过请求对象的方法来获取这些信息
获取请求行
StringBuffer getRequestURL() //完整的URL
String getRequestURI() //请求行中的资源路径
String getMethod() //请求方式
String getContextPath() //当前项目的路径
String getQueryString() //请求行中资源路径后面的参数
注意:
getRequestURL()返回的是一个可变字符串,不能直接使用String来接收
getQueryString()获取的是资源路径后面的参数,请求体里的数据无法获取
09_获取请求头
String getHeader(String name) //通过name来获取请求头value
Enumeration getHeaderNames() //获取所有的请求头name
Enumeration迭代遍历
Enumeration<String> e = request.getHeaderNames();
while(e.hasMoreElements()) {
String name = e.nextElement();
System.out.println(name);
}
10_获取表单提交的数据
String getParameter(String name) :根据表单项的name来获取表单项的value
注意:
有表单项提交过来,但是没有值, 打印的是空字符串
表单项根本没有提交过来,打印的就是null,就不能调用字符串的方法,否则会报空指针异常
11_获取表单提交的数据2
String[] getParameterValues(String name) 根据表单项的name获取表单项value的数组
应用场景: name是重复的,比如密码确认密码 复选框
12_获取表单提交的数据3
Map getParameterMap(): 获取表单提交来的所有数据,并封装成一个map返回,一些框架(工具类)会使用这个方法
Enumeration getParameterNames() 获取提交过来表单项所有的name
返回值使用泛型时应该是Map<String,String[]>形式,
因为有时像checkbox这样的组件会有一个name对应对个value的时候,
所以该Map中键值对是<String-->String[]>的实现。
注意:
注册按钮提交过来没有意义,所以注册按钮千万不要写个name属性
14_获取表单提交的数据乱码的处理
原因:
编码前后不一致
表单提交数据用的是UTF-8
请求对象接收数据转换成字符串 用的是默认的ISO-8859-1
对于post请求
request.setCharacterEncoding("UTF-8");//只能处理请求体,这里设置请求对象创建字符串所使用的编码是UTF-8
对于get请求
浏览器
按照表单页面的编码(UTF-8)进行转码,转成字节数组,拼接在请求资源的后面
接下来把字节数组做一个转义(url编码)在发送
服务器
服务器首先拿到这个数据做一个url解码,(正确的)
然后把解码之后的数据按照ISO-8859-1拼成字符串(错误)
做法:
//把字符串打回原形
byte[] bys = request.getParameter("username").getBytes("ISO-8859-1");
//把字节数组按照正确的编码转换字符串
String username = new String(bys,"UTF-8");
15_转发和包含
用ServletContext实现转发和包含,路径必须以正斜杠开头
RequestDispatcher rd = getServletContext().getRequestDispatcher("/register.html");
rd.forward(request, response);
rd.include(request, response);
用request对象实现转发和包含,路径可以不用正斜杠开头
RequestDispatcher rd = request.getRequestDispatcher("register.html");
rd.forward(request, response);
rd.include(request, response);
16_使用请求对象实现数据共享
ServletContext 上下文对象 范围是当前的web应用
时间范围 tomcat 一加载项目 tomcat关闭
空间范围 整个web应用
request 请求对象 范围是当前的请求 需要同一个请求才能实现数据的共享
时间范围 一个请求开始,请求结束
空间范围 当前这个请求里面
//设置数据
request.setAttribute("username", "zhangsan");
//获取数据
Object obj = request.getAttribute("username");
System.out.println(obj);
//删除数据
request.removeAttribute("username");
//转发
RequestDispatcher rd = request.getRequestDispatcher("/RequestDemo9");
rd.forward(request, response);
访问网站访问量