文章目录
- 过滤器
- 什么是过滤器
- 如何编写过滤器
- 过滤器的原理
- 多个过滤器执行顺序
- 监听器
- 什么是监听器?
- 监听器的作用
- 监听器的相关概念
- 编写一个监听对象的监听器
- 文件上传与下载
- 文件上传
- 使用Serlvet3.0方式进行文件上传
过滤器
之前写的登录案例中,用户可以通过输入地址直接跳过登录,这种情况是不应该出现的,因此我们需要使用过滤器来限制
什么是过滤器
过滤器是一种web开发中用于过滤请求的技术手段。用于限制上面这种情况
如何编写过滤器
1.编写一个普通xxxFilter
2.配置该过滤器要拦截哪些请求
3.重写doFilter方法
4.在doFilter方法中编写过滤的逻辑代码
案例:
//对所有页面进行过滤
@WebFilter(value = "/*")
public class MyFilter implements Filter {
//白名单
String[] whiteUrlArr={"/login.jsp","/login","/register.jsp","/register"};
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//设置编码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//取出初始化参数中的值
//白名单中url直接放行
String uri = req.getRequestURI();
for (String s : whiteUrlArr) {
if(s.equals(uri)){
filterChain.doFilter(req, resp);
System.out.println("白名单之后");
return;
}
}
Object user = req.getSession().getAttribute("user");
if(user==null){//没登录
resp.sendRedirect("login.jsp");
return;
}
//调用后面资源链
filterChain.doFilter(req, resp);
System.out.println("666");
}
@Override
public void destroy() {
System.out.println("销毁");
}
}
过滤器的原理
过滤器的执行时机远远早于Servlet,因此请求会先经过Filter,在Filter决定是继续执行,还是打回去。
多个过滤器执行顺序
- 按照过滤器的名称进行排列顺序
- 多个过滤器执行顺序是先进后出
监听器
什么是监听器?
监听器是Web三大组件之一(Servlet、Filter、Lisener)。
监听器的作用
- 监听Web组件的状态或属性变化情况
- 监听对象(什么时候被注册,什么时候被销毁)
1.ServletContext
2.HttpSession
3.ServletRequest - 监听对象属性变化
监听器的相关概念
1.事件(创建)
2.事件源(要监听哪个对象)
3.监听器(逻辑代码)
4.注册事件(监听器与事件进行绑定)
编写一个监听对象的监听器
1.编写一个普通xxxListener
2.实现xxxListener接口(xxx为上面监听器作用中的监听对象)
3.配置@WebListener注解
4.完成监听代码
具体案例:
利用ServletContext会在一开始创建的原理,监听它用于创建连接池
@WebListener
public class MyListener implements ServletContextListener {
@SneakyThrows
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext创建了");
Class.forName("com.blb.utils.JdbcTemplateUtils");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext销毁了");
}
}
文件上传与下载
文件上传
1.Servlet3.0之后提供了文件上传功能
2.Apache file-upload组件上传
使用Serlvet3.0方式进行文件上传
1.编写文件上传界面
form一定要加 enctype="multipart/form-data"
必须使用post请求
2.编写文件上传Servlet
必须加上@MultipartConfig
具体案例:
将用户上传的文件保存到服务器
jsp代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<div align="center" style="text-align: center">
<h1>上传文件</h1>
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<button>上传</button>
</form>
</div>
</body>
</html>
java代码
@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取上传到服务器的临时文件对象
Part part = req.getPart("file");
//获取上传的文件名 123.jpg
String submittedFileName = part.getSubmittedFileName();
//获取临时文件的输入流
InputStream inputStream = part.getInputStream();
//构建文件输出流
FileOutputStream os = new FileOutputStream("E:/upload/"+submittedFileName);
//IO流读写操作
byte[] data = new byte[10240];
while (true){
int len = in.read(data);
if(len==-1){
break;
}
os.write(data,0,len);
}
os.close();
in.close();
req.getRequestDispatcher("upload.jsp").forward(req,resp);
}
}
下载
上传写完了,那就来写下载
现在上传页面添加一个a标签,用于跳转
<br><a href="index">点此去下载文件</a>
然后新建一个下载页面(index.jsp)和初始化(index)
下载页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>文件下载</title>
</head>
<body>
<div align="center" style="text-align: center">
<h1>文件列表</h1>
<%--用于跳转下载--%>
<h2><a href="upload.jsp">点此去上传文件</a><br></h2>
<%--循环输出文件列表--%>
<c:forEach items="${list}" var="file">
<%--添加下载链接--%>
<a href="/download?name=${file}">${file}</a><br>
</c:forEach>
</div>
</body>
</html>
初始化java代码
public class indexServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建File对象,指向文件上传的目录
File file=new File("c:/upload/");
//获取该目录下的文件列表
String[] list = file.list();
//将文件列表存到request作用域
req.setAttribute("list", list);
//转发到index.jsp
req.getRequestDispatcher("/index.jsp").forward(req, resp);
}
}
下载java代码
@WebServlet("/download")
public class downloadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要下载文件名
String name = req.getParameter("name");
//构建文件输入流
FileInputStream is = new FileInputStream("c:/upload/" + name);
//获取文件大小
int len = is.available();
//构建输出流
ServletOutputStream os = resp.getOutputStream();
//IO流读写操作
IOUtils.readAndWrite(is,os);
}
}
经过运行我们发现几个问题
- 点击txt、png等常用后缀是会是打开,而不是下载
- 下载时一律显示download而不是文件名
- 下载时不会显示总文件大小
因此我们
//1.告诉浏览器文件类型是二进制文件
resp.setContentType("application/octet-stream");
//2.告诉浏览器文件名
resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(name,"utf-8"));
//3.告诉浏览器文件大小
resp.setContentLength(len);