ServletContext对象:
1.概念:代表整个web应用,可以和程序的容器(服务器)进行通信(其实可以看成一个全局对象)。例如,获取文件的 MIME 类型、分发请求或写入日志文件
2.获取ServletContext对象:
- 通过request对象获取:request.getServletContext();
- 通过HttpServlet获取:this.getServletContext();
3.功能:
a. 获取MIME类型:public String getMimeType(String file) 如果类型未知则返回null,在web.xml里面可以查看相关的mime类型
MIME类型:在互联网通信过程中定义的一种文件数据类型,格式------ 大类型/小类型 text/html image/jpg
b.域对象:共享数据
- public void setAttribute(String name, Object object)
- public Object getAttribute(String name)
- public void removeAttribute(String name)
c.获取文件的真实(服务器)路径:public String getRealPath(String path) path是路径的字符串格式
如下:分别获取src目录下a.txt,web目录下b.txt,WEB-INF目录下的文件的真实路径c.txt
package com.servletcontext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 承夕
* @date 2020/2/18 0018 - 8:44
* @contact:https://github.com/chengxi0
*/
@WebServlet("/servletContextDemo1")
public class ServletContextDemo1 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext context = this.getServletContext();
//分别获取src目录下,web目录下,WEB-INF目录下的文件的真实路径
//获取web目录下的a.txt
String realPath1 = context.getRealPath("b.txt");
System.out.println("b : " +realPath1);
String realPath2 = context.getRealPath("WEB-INF/c.txt");
System.out.println("c : " +realPath2);
String realPath3 = context.getRealPath("WEB-INF/classes/a.txt");
System.out.println("a : " +realPath3);
/* b : G:\Java文件\Tomcat\out\artifacts\Tomcat_war_exploded\b.txt
c : G:\Java文件\Tomcat\out\artifacts\Tomcat_war_exploded\WEB-INF\c.txt
a : G:\Java文件\Tomcat\out\artifacts\Tomcat_war_exploded\WEB-INF\classes\a.txt*/
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
输出结果可以看出,String path 只需要填进相对于部署在Tomcat上的路径就ok了,但是因为使用IDEA部署的tomcat因此,真正运行在Tomcat服务器的是“G:\Java文件\Tomcat\out\artifacts\Tomcat_war_exploded”这个目录下的,因此里面也没有src目录,但是在WEB-INF文件夹里面有classes目录,即原项目src目录下的文件会放在这个classes目录下。
案例:文件下载(页面显示超链接,用户点击后弹出下载提示框完成文件下载)
这里有个需要知道的知识点:
超链接指向的资源如果是能够被浏览器解析的话,就会在浏览器上面展示出来,如果不能解释,就会弹出下载提示框,因此如果需要任何资源都弹出下载提示框,那么可以使用响应头设置资源的打开方式:
content-disposition:attachment ;filename=xxx
package com.servletcontext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @author 承夕
* @date 2020/2/18 0018 - 8:44
* @contact:https://github.com/chengxi0
*/
@WebServlet("/servletContextDemo2")
public class ServletContextDemo2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取文件名
String filename = request.getParameter("filename");
//读取部署在服务器的的文件资源
String realPath = this.getServletContext().getRealPath("photoes/"+filename);
File file = new File(realPath);
FileInputStream fileInputStream = new FileInputStream(file);
//设置响应头
response.setHeader("content-type",this.getServletContext().getMimeType(filename) );
response.setHeader("content-disposition","attachment;filename="+filename);
//输入输出流之间的操作
ServletOutputStream outputStream = response.getOutputStream();
int len =0 ;
byte[] brr = new byte[1024*8];
while ((len = fileInputStream.read(brr)) != -1) {
outputStream.write(brr,0,len);
}
fileInputStream.close();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下载页面</title>
</head>
<body>
<a href="/Tomcat_war_exploded/servletContextDemo2?filename=codetable.jpg">点击下载文件</a>
</body>
</html>
如果图片名是中文的话出现的乱码问题(本次只对谷歌浏览器):
需要在设置响应头content-disposition之前把filename进行url编码,然后在浏览器以附件的形式显示文件名的时候让浏览器自己根据ulr解码进而显示正确的中文名,而不是乱码。
(显示是由浏览器去解码的,我们在servlet内部把中文按照url编码即可)但是需要注意的是,在不同的浏览器,对文件名的解码方式不一样,比如火狐使用的是64为的编码,因此这就需要了解浏览器不一样解码引起的兼容性问题。
POST方式提交的表单参数是中文的乱码问题
Tomcat8已经支持了GET方式获取表单参数是中文的情况了,但是POST方式还没支持。因此需要正确获取到这些带中文的表单参数,需要在开头就设置。
利用response对象往页面打印东西时的乱码问题
往页面写有中文的数据,那就需要建议浏览器以上面格式去读取这些数据,因此只需要在写数据之前设置,浏览器的编码就行.
会话
概念:一次会话包含多次请求和响应,从浏览器第一次给服务器发出请求,到有一方断开为止.
功能:在一次会话范围内的多次请求和响应之间共享数据
方式:
- 客户端会话技术:Cookie
- 服务器会话技术:Session
Cookie
概念:客户端绘画技术,把数据保存到客户端.
主要步骤:
- 创建Cookie对象,绑定数据 : new Cookie(String name, String value)
- 发送Cookie对象: void addCookie(Cookie cookie) 利用response对象的addCookie方法
- 获取Cookie: Cookie[] getCookies() 可以是多个Cookie
还有一些Cookie对象常用方法
- 获取Cookie的名称 :String getName()
- 返回 cookie 的值 :String getValue()
- 设置 cookie 的最大生存时间,以秒为单位 :void setMaxAge(int expiry) expiry负值意味着 cookie 不会被持久存储,将在 Web 浏览器退出时删除。0 值会导致删除 cookie,正整数表示该Cookie生存的最长时间.
特点和作用:
- Cookie存储数据是在客户端,因此一般用于存储少量的不太敏感的数据
- 浏览器对于单个Cookie的大小有限制(4kb),以及同一个域名下的总Cookie数量也有限制(20)
- 在不登录的情况下,完成服务器对客户端的身份识别.
注意点:
- Cookie是可以存储中文数据,这个特性这Tomcat8之后支持了.
- Cookie默认下是本项目下共享数据的,但是如果需要多个项目共享数据,那么需要使用setPath(String path)方法进行设置,把path设置为"/"表示根目录就ok了
案例:记住上一次的访问时间.如果是第一次访问打印"你好,欢迎首次访问"如果不是第一次访问,"欢迎回来,你上一次访问的时间为:显示时间字符串"
package com.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.DoubleAccumulator;
/**
* @author 承夕
* @date 2020/2/18 0018 - 8:44
* @contact:https://github.com/chengxi0
*/
@WebServlet("/cookiedemo1")
public class CookieDemo1 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
response.setContentType("text/html;charset=utf-8");
//获取cookies
Cookie[] cookies = request.getCookies();
//遍历cookies看看是否已经创建
Cookie cc = null ;
boolean flag = false ;
if(cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
String name = c.getName();
if (name.equals("time")) {
cc = c ;
flag = true ;
break ;
}
}
}
//创建时间对象
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒");
String format = simpleDateFormat.format(date);
//设置编码格式
format = URLEncoder.encode(format, "utf-8");
if (flag) {
String ccValue = cc.getValue();
String ccdecode = URLDecoder.decode(ccValue, "utf-8");
response.getWriter().println("欢迎再次访问,上次访问时间为 :" + ccdecode);
cc.setValue(format);
cc.setMaxAge(60*60*24*30);
//一定要在设置cookie的数据之后进行response.addCookie()不然浏览器不会保存的
response.addCookie(cc);
}
else {
//创建cookie,绑定数据
Cookie cookie = new Cookie("time", format);
cookie.setMaxAge(60*60*24*30);
String ccdecode1 = URLDecoder.decode(format, "utf-8");
System.out.println(ccdecode1);
//还要添加到响应
response.addCookie(cookie);
response.getWriter().println("欢迎首次访问");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}