JavaWeb-day05-过滤器与监听器与文件上传下载


过滤器

之前写的登录案例中,用户可以通过输入地址直接跳过登录,这种情况是不应该出现的,因此我们需要使用过滤器来限制

什么是过滤器

过滤器是一种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)。

监听器的作用

  1. 监听Web组件的状态或属性变化情况

  2. 监听对象(什么时候被注册,什么时候被销毁)
    1.ServletContext
    2.HttpSession
    3.ServletRequest

  3. 监听对象属性变化

监听器的相关概念

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);
    }
}

经过运行我们发现几个问题

  1. 点击txt、png等常用后缀是会是打开,而不是下载
  2. 下载时一律显示download而不是文件名
  3. 下载时不会显示总文件大小
    因此我们
//1.告诉浏览器文件类型是二进制文件
resp.setContentType("application/octet-stream");
//2.告诉浏览器文件名
resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(name,"utf-8"));
//3.告诉浏览器文件大小
resp.setContentLength(len);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值