目录
1.文件下载
1.1超链接下载:
1.2自定义servlet下载
1.3小结
2.点击切换验证码
2.1前置只是-验证码生成
2.2分析及代码实现
2.3需求2:点击切换验证码-绕过缓存
3.几种获取preperties资源方式
作者简介:大家好呀!我是爱吃豆的土豆
个人主页:【爱吃豆的土豆的博客_CSDN博客-Web知识,spring框架,vue领域博主】
博主信息:人必有所执,方能有所成!希望大家多多支持一起进步呀!
若有帮助,还请【关注➕点赞➕收藏】,不行的话我再努力努力呀!
⚡版权声明:本文由【爱吃豆的土豆的博客】原创、在CSDN首发、需要转载请联系博主。
超链接下载方式
自定义Servlet下载
通过自定义Servlet 完善超链接下载,可以下载中文名资源
http://localhost:8080/day08_1/download/hello.jpg
浏览器发来的所有请求,都会进行url-pattern.
完全匹配:尝试寻找servlet,路径为download/hello.jpg,寻找不到,进入下一个匹配
目录匹配:尝试寻找servlet,目录路径为/download/*,寻找不到,进入下个匹配
扩展名匹配:尝试寻找servlet,扩展名为:*.jpg,寻找不到,进入最终匹配
缺省匹配:访问DefaultServlet,把当前/download/hello.jpg,对应的资源通过IO流读取到,写出到响应体中。
超链接下载资源的本质:依靠DefaultServlet。
DefaultServlet遵循的码表为iso8859-1,使得utf-8编码的中文资源名,被解析为乱码,通过乱码无法定位资源的,导致资源找不到。
本质:模仿DefaultServlet,并且将资源名解决乱码
new String("乱码".getBytes("iso8859-1"),"utf-8");
download.html
自定义Servlet下载
hello.jpg
你好.rar
DownLoadServlet
@WebServlet({"/dl"})
public class DownLoadServlet extends BaseServlet {
/**
* 文件下载
*/
public void download() throws IOException {
//1、获取参数filename
String filename = getRequest().getParameter("filename");
//2、处理文件名乱码
String resourceName = new String(filename.getBytes("iso8859-1"), "utf-8");
//3、设置强制弹出下载窗口
HttpServletResponse response = getResponse();
// 传递的文件名应该是原来乱码的filename,这样下载窗口经过解码后,就会解为正常内容
response.setHeader("Content-Disposition","attachment;filename="+filename);
//4、读取资源文件
//4.1、资源的绝对路径
String filePath = getServletContext().getRealPath("/")+"/download/"+resourceName;
//4.2、文件流读取
FileInputStream fis = new FileInputStream(filePath);
//5、写出响应体
//5.1、获取响应体字节流
ServletOutputStream out = response.getOutputStream();
//5.2、使用工具流复制
IOUtils.copy(fis,out);
fis.close();
//因为out流被tomcat控制的,所以不要手动关闭,由tomcat管理
}
}
小结:
文件下载:服务器把数据传递给浏览器(响应体)
文件下载,默认依赖的是DefaultServlet,因为解码码表为iso8859-1,会导致中文资源名乱码,导致无法找到。
自定义Servlet下载:
强制下载的响应头:response.setHeader("Content-Disposition","attchment;filename="+下载名);
必须位于 getOutputStream()之前,否则失效。
@WebServlet({"/vc"})
public class VerfityCodeServlet extends BaseServlet {
public void vc() throws IOException {
//若需要看到指定图片,需要手动设置响应体(必须在响应体操作之前设置)
getResponse().setContentType("image/jpeg;charset=utf-8");
//向响应体写出一张图片形式的验证码
String vc = createVerifyCodeImage();
System.out.println(vc);
}
}
小结:
验证码本质是一张图片,以响应体的方式传递给浏览器(文件下载)
为了让浏览器打开解析,需要在响应体操作之前,设置响应体类型:
getResponse().setContentType("image/jpeg;charset=utf-8")
login.html
VerifyCodeServlet已经在前置知识完成了。
用户默认开启缓存,存在缓存问题:
因为每次路径都是/day08_1/vc?method=vc ,第一次访问时,该路径就在浏览器上有一张图片了。
缓存理解为一个map集合:
Key value
Url路径 该路径的资源
/day08_1/vc?method=vc 验证码图片
下次再准备发请求时,发现该路径在浏览器有缓存,直接使用浏览器缓存,而不去请求服务器。
解决方案:
绕过缓存,只需要让缓存的地址(key)不同,参数列表,只需要让参数列表每次不同,缓存的地址不同
可以用随机数
可以用毫秒值
小结:
因为用户端访问时存在缓存问题。
为了绕过缓存,需要让每次URL访问路径不同。
让URL最后加入随机的参数列表就可以。
目标:掌握ServletContext方式获取properties资源方式
public void run1() throws IOException {
//类加载器获取资源:SE方式(不启动服务器也能正常执行)
InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/p/d1.properties");
Properties p1 = new Properties();
p1.load(is);
System.out.println(p1);
//ServletContext获取资源:EE方式(必须先启动服务器才能正常执行)
InputStream is2 = getServletContext().getResourceAsStream("/WEB-INF/classes/com/p/d1.properties");
Properties p2 = new Properties();
p2.load(is2);
System.out.println(p2);
//ResourceBundle获取:SE方式(不启动服务器也能正常执行)
ResourceBundle bundle = ResourceBundle.getBundle("com.p.d1");
System.out.println(bundle.getString("uname"));
}
小结:
建议使用的是ServletContext的getResourceAsStream,该方式的出发目录是发布目录的根目录,不仅能够获取properties,而且还能获取其他资源。
其他两种方
注意:
1、以上三种获取资源方式,获取的是 发布目录下的资源。
2、ResourceBundle相同路径文件在服务器启动期间,为了防止重复加载浪费内容,会加载一次
(重新加载,默认关闭服务器,服务器关闭时会卸载内存)
式,出发目录都是 发布目录的/classes 目录