JavaWEB(下)

WEB服务器

什么是WEB服务器

在这里插入图片描述

静态资源和动态资源

在这里插入图片描述

常用的服务器产品

在这里插入图片描述

Tomcat简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Tomcat的启动和关闭

在这里插入图片描述
在这里插入图片描述

web项目部署

在这里插入图片描述

浏览器访问WEB服务器

在这里插入图片描述

Tomcat服务器请求响应流程

在这里插入图片描述
在这里插入图片描述

HTTP协议

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

HTTP协议通信规则

在这里插入图片描述

HTTP请求规则

下面就是浏览器的请求内容

在这里插入图片描述

HTTP响应规则

在这里插入图片描述
自定义浏览器

package com.qfedu.http.response;
  
  import jdk.internal.util.xml.impl.Input;
  
  import java.io.*;
  import java.net.Socket;
  
  /**
   * @Description
   * @Author 千锋涛哥
   * 公众号: Java架构栈
   */
  public class MyBrowser {
  
      public static void main(String[] args) throws IOException {
          //将上一个案例中浏览器发送给 MyHttpServer的 http请求内容,发送给百度
  
          // 1.向百度服务器发送链接请求
          Socket socket = new Socket("www.baidu.com", 80);
          // 2.通过链接中的输出流,将HTTP请求内容发送给百度
          OutputStream outputStream = socket.getOutputStream();
          PrintWriter out = new PrintWriter(outputStream);
          out.println("GET /s HTTP/1.1");
          out.println("Host: www.baidu.com:80");
          out.println("Connection: keep-alive");
          out.println("sec-ch-ua: \"Google Chrome\";v=\"95\", \"Chromium\";v=\"95\", \";Not A Brand\";v=\"99\"");
          out.println("sec-ch-ua-mobile: ?0");
          out.println("sec-ch-ua-platform: \"Windows\"");
          out.println("Upgrade-Insecure-Requests: 1");
          out.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36");
          out.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
          out.println("Sec-Fetch-Site: none");
          out.println("Sec-Fetch-Mode: navigate");
          out.println("Sec-Fetch-User: ?1");
          out.println("Sec-Fetch-Dest: document");
          out.println("Accept-Encoding: gzip, deflate, br");
          out.println("Accept-Language: zh-CN,zh;q=0.9");
          out.println("");
          out.flush();
          //3.通过输入流接受百度的响应数据(HTTP响应规则)
          BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          String responseContent = null;
          while( (responseContent = reader.readLine())!=null){
              System.out.println(responseContent);
          }
  
      }
  }

HTTP响应内容

在这里插入图片描述

HTTP响应状态码

在这里插入图片描述

Servlet

Servlet简介

在这里插入图片描述

JavaWeb工程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
javaweb 工程目录
在这里插入图片描述

创建Servlet

在这里插入图片描述

配置servlet

在这里插入图片描述

基于web.xml配置servlet

在这里插入图片描述

基于注解配置Servlet

在这里插入图片描述

IDEA部署WEB项目

在这里插入图片描述
如果创建项目的时候已经配置了,web服务器者可以直接按照上面的步骤执行即可,如果没有配置服务器则需要按照下面的方法配置服务器

配置服务器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后下面的步骤就和上面的第一种情况一致

浏览器访问测试

通过浏览器发送请求,访问tomcat中web项目的servlet类
在这里插入图片描述

GET请求和POST请求

GET提交

在这里插入图片描述
在这里插入图片描述

POST提交

在这里插入图片描述
在这里插入图片描述

Servlet响应动态网页案例

在这里插入图片描述

实现代码:

package com.qfedu.test1.dto;

/**
 * @Description 图书实体类
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
public class Book {
    private String bookId;
    private String bookName;
    private String bookAuthor;
    private double bookPrice;
    private String bookImgPath;
	//无参构造器
	//全参构造器
    //get 和 set方法
}
package com.qfedu.test1;

import com.qfedu.test1.dto.Book;

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;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description 根据图书ID查询一个图书信息
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
@WebServlet("/book-query")
public class BookQueryServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("BookQueryServlet--------doPost");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("BookQueryServlet--------doGet");
        //动态生成HTML
        // 1.接收到浏览器请求时传递的图书ID (bookId)
        String bid = request.getParameter("bookId");

        // 2.根据bid查询数据库图书表(伪代码)
        Map<String, Book> bookMap = new HashMap<>();
        bookMap.put("1001",new Book("1001","Java","张三",55.66,""));
        bookMap.put("1002",new Book("1002","C++","李四",33.44,""));
        bookMap.put("1003",new Book("1003","Python","王五",44.55,""));
        // book就是根据用户请求查询到的动态数据
        Book book = bookMap.get(bid);

        // 3.将查询到图书信息生成网页,将网页响应给浏览器:通过IO流(输出流)向浏览器响应一个网页数据
        // 这个out对象,就是用于响应浏览器的输出流,通过这个输出流写出什么数据,浏览器就可以接受到什么数据
        // a.设置响应头
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        // b.通过输出流响应网页数据
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head><meta charset='utf-8'><title>这是Servlet响应的网页</title></head>");
        out.println("<body>");
        out.println("<table style='border:1px deepskublue solid; width:1000px;' align='center' border='1' cellspacing='0'>");
        out.println("<tr><th>图书编号</th><th>图书名称</th><th>图书作者</th><th>图书价格</th><th>图书封面</th></tr>");
        out.println("<tr>");
        out.println("<td>"+book.getBookId()+"</td>");
        out.println("<td>"+book.getBookName()+"</td>");
        out.println("<td>"+book.getBookAuthor()+"</td>");
        out.println("<td>"+book.getBookPrice()+"</td>");
        out.println("<td>"+book.getBookImgPath()+"</td>");
        out.println("</tr>");
        out.println("</table>");
        out.println("</body>");
        out.println("</html>");
        out.flush();
        out.close();
    }
}

Servlet动态请求与核心类接口

在这里插入图片描述

Servlet类处理用户请求的流程

在这里插入图片描述

Servlet实例的生命周期

在这里插入图片描述
在这里插入图片描述

Servlet线程安全问题

在这里插入图片描述

Servlet开发技术

在这里插入图片描述
在这里插入图片描述
也就是说我们向服务器发送的请求会被封装成一个对象,所以我们下面要学的就是如何从这个对象中获取我们想要的信息

获取请求行的数据

在这里插入图片描述
在这里插入图片描述

获取请求头中的数据

在这里插入图片描述

在这里插入图片描述

获取请求正文中的数据

在这里插入图片描述
在这里插入图片描述

request对象常用方法

在这里插入图片描述
在这里插入图片描述

Servlet类接受表单数据的案例

图书添加操作:需要从图书添加页面提交数据到Servlet

book-add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>提交图书</title>
</head>
<body>
    <form action="http://localhost/demo3/BookAddServlet" method="get">
        <p>图书编号:<input type="text" name="bookId"/></p>
        <p>图书名称:<input type="text" name="bookName"/></p>
        <p>图书作者:<input type="text" name="bookAuthor"/></p>
        <p>图书价格:<input type="text" name="bookPrice"/></p>
        <p><input type="submit" value="Get提交"/></p>
    </form>

    <hr/>

    <form action="http://localhost/demo3/BookAddServlet" method="post">
        <p>图书编号:<input type="text" name="bookId"/></p>
        <p>图书名称:<input type="text" name="bookName"/></p>
        <p>图书作者:<input type="text" name="bookAuthor"/></p>
        <p>图书价格:<input type="text" name="bookPrice"/></p>
        <p><input type="submit" value="Post提交"/></p>
    </form>
</body>
</html>

BookAddServlet

package com.qfedu.servlets;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @Description 添加图书
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
@WebServlet("/BookAddServlet")
public class BookAddServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        //getParameter 方法参数字符串 必须要和 form表单中输入框的name属性一致
        //              此方法获取的客户端提交的数据一律为String类型,根据需要可以进行类型转换
        int id = Integer.parseInt(request.getParameter("bookId"));//5
        String name = request.getParameter("bookName");
        String author = request.getParameter("bookAuthor");
        double price = Double.parseDouble(request.getParameter("bookPrice"));

        System.out.println("图书编号:"+id);
        System.out.println("图书名称:"+name);
        System.out.println("图书作者:"+author);
        System.out.println("图书价格:"+price);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        // 如果页面采用form表单post方式提交数据,数据是通过 请求正文 传递的
        // 1.我们可以通过请求正文获取数据
        //ServletInputStream inputStream = request.getInputStream();
        //BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        //String s = reader.readLine();
        //System.out.println("请求正文数据:"+s);

        // 2.form表单post方式提交的数据,也可以通过request对象的getParameter方法接收,
        //   之前是不能打开request输入流
        int id = Integer.parseInt(request.getParameter("bookId"));//5
        String name = request.getParameter("bookName");
        String author = request.getParameter("bookAuthor");
        double price = Double.parseDouble(request.getParameter("bookPrice"));

        System.out.println("图书编号:"+id);
        System.out.println("图书名称:"+name);
        System.out.println("图书作者:"+author);
        System.out.println("图书价格:"+price);
    }

}

使用request对象处理上面案例中提交中文乱码问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过httpServletResponse对象来响应http请求

在这里插入图片描述

学生成绩查询案例

在这里插入图片描述

项目环境搭建

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

相应的环境搭建代码:
properties

# 数据库连接信息
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8
username=root
password=235374Hh

# 连接池属性
# 连接池的初始化连接数<创建数据库连接池时默认初始化的连接的个数>
initialSize=10
# 连接池的最大连接数
maxActive=50
# 最小空闲连接数(当数据库连接使用率很低时,连接池中的连接会被释放一部分)
minIdle=5
# 超时等待时间(单位:ms)
maxWait=30000

DruidUtils

public class DruidUtils {
    //1.定义DruidDataSource对象:表示Druid数据库连接池(数据源)
    private static DruidDataSource druidDataSource;

    //2.静态代码块初始化定义DruidDataSource对象
    static{
        try {
            //读取druid.properties文件中配置的属性
            InputStream is = DruidUtils.class.getResourceAsStream("druid.properties");
            Properties properties = new Properties();
            properties.load(is);
            //使用属性文件初始化DruidDataSource对象
            druidDataSource =
                    (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //3.创建静态方法,从连接池对象中获取连接
    public static Connection getConnection(){
        Connection connection = null;
        try {
            connection =  druidDataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

}

剩下的那些就不搞了,跟我们平时项目的思路不太一致

sevlet的转发

1. 转发跳转流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-307p9IXN-1659148002950)(imgs/image-20211110015605551.png)]

2. 转发的特点
  • 转发是在服务器端,两个Servlet之间的请求行为;
  • 浏览器只对服务器进行了一次请求;
  • 浏览器的地址不会改变,浏览器请求ServletA,ServletA转到ServletB由ServletB响应浏览器,浏览器显示的是ServletA的访问地址;
  • 转发过程中,可以通过request对象传递数据;
3. 转发的代码实现
  • ServletA 转发到 ServletB
在ServletA中:
request.getRequestDispatcher(“ServletB的URL”).forward(request,response);
4. 数据传递
  • ServletA 转发到 ServletB,并传递参数
  • 传数据
//ServletA:在转发操作之前,将需要传递给ServletB的参数设置到request对象中,可以传递不同类型数据
//设置转发传递的数据
request.setAttribute("stuNum","10001");
request.setAttribute("stuAge",21);	//如果直接给简单类型数据,则会自动装箱为对应的封装类对象
request.setAttribute("stu",new Student(...));
//转发
request.getRequestDispatcher("ServletB的URL").forward(request,response);
  • 取数据
//ServletB:在ServletB的doGet/doPost方法中,通过request对象获取ServletA传递的参数
//Object obj = request.getAttribute(String key);
String snum = (String)request.getAttribute("stuNum");
int sage = (Integer)request.getAttribute("stuAge");
Student stu = (Studennt)request.getAttribute("stu");
sevlet的重定向
1. 重定向跳转流程
  • 客户端请求ServletA,ServletA响应给客户端一个新的请求地址ServletB,让客户端重新向ServeltB发送请求。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4LorJhfp-1659148002952)(imgs/image-20211110015625536.png)]

2. 重定向特点
  • 重定向是客户端的行为

  • 浏览器对服务器发送了两次请求;

  • 重定向是由浏览器再次发送请求,浏览器地址会改变为转发的地址;

  • 不能通过request对象将ServletA中的数据传递给ServletB

  • 如果ServletA重定向到ServletB的时候有数据要传递到ServletB该如何实现?——url传值

3. 重定向代码实现
在ServletA中
response.sendRedirect(“ServletB访问URL”);
4. 数据传递
//ServletA:在响应浏览器重定向地址的时候,在URL声明参数
response.sendRedirect("ServletB?key=value");
//ServletB: 获取浏览器请求的参数
String value = request.getParameter("key");

状态管理

在这里插入图片描述

状态管理实现

在这里插入图片描述

在这里插入图片描述

cookie的使用

在这里插入图片描述

在这里插入图片描述

案例如下:
在这里插入图片描述
在这里插入图片描述

代码如下:
在这里插入图片描述

-创建两个Servlet类,分别为FirstServletSecondServlet

1. 写Cookie到浏览器
  • 创建cookie Cookie cookie = new Cookie("key1", "value1");
  • 设置cookie cookie.setMaxAge(24*60*60);
  • 写cookie response.addCookie(cookie);
  • 服务器可以同时写多个Cookie存储到客户端
package com.qfedu.servlets;

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.io.PrintWriter;

/**
 * @Description 写Cookie
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //向浏览器存储一个Cookie
        // 1. 创建Cookie对象  (javax.servlet.http.Cookie)
        Cookie cookie = new Cookie("key1", "value1");

        // 设置cookie生命周期
        // 情况1:如果设置>0的值,表示设置cookie有效时间(单位s)
        // 情况2:如果参数=0,表示浏览器关闭销毁cookie
        // 情况3:如果参数=-1,表示内存存储
        cookie.setMaxAge(24*60*60);

        // 2. 将cookie对象添加到HTTP响应头,写Cookie到客户端
        response.addCookie(cookie);

        //响应浏览器一个界面
        //a.设置响应头
        response.setStatus(200);
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        //b.响应正文
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset='utf-8'>");
        out.println("<title></title>");
        out.println("<body>");
        out.println("<a href='SecondServlet'>请求SecondServlet</a>");
        out.println("</body>");
        out.println("</head>");
        out.println("</html>");
        out.flush();
        out.close();
    }
}
2. 服务器读取Cookie
  • 通过request对象获取所有cookie: Cookie[] cookies = request.getCookies();
  • 获取Cookie对象的key: String key = cookie.getName();
  • 获取Cookie对象的value:String value = cookie.getValue();
package com.qfedu.servlets;

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;

/**
 * @Description 读Cookie
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
@WebServlet("/SecondServlet")
public class SecondServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 读取cookie: 当客户端再次请求服务器时,通过request将cookie传递到服务器
        // 通过request对象获取浏览器传递的cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie: cookies) {
            String key = cookie.getName();
            String value = cookie.getValue();
            System.out.println(key+"对应的值:"+value);
        }
        // SecondServlet暂时不响应浏览器
    }
}
Cookie的优点和限制

优点:

  • 可以灵活的配置过期规则
  • 简洁,cookie中存储的是最简单的键值对格式的文本数据
  • 数据的持久性,保存到浏览器中的cookie在过期之前是持久存储的

限制:

  • 存储数据的大小,大多浏览器支持4k、8k的数据存储
  • 用户可以通过浏览器设置禁用Cookie,因此限制了cookie的使用场景(如果一定要使用cookie,可以检查浏览器cookie是否可用,如果不可用提醒用户设置开启cookie)
  • cookie是存储在客户端浏览器中的,有被纂改的风险,有潜在的安全隐患

Session对象

在这里插入图片描述

在这里插入图片描述
session的原理
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
注意上面所有的过程都是由服务器和浏览器自动完成

获取session对象

在这里插入图片描述

session对象数据操作

在这里插入图片描述

session对象失效

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

request与session的区别

在这里插入图片描述
在这里插入图片描述

request中数据间可以流通的方式

在这里插入图片描述
session中数据间可以流通的方式

在这里插入图片描述

ServletContext对象

在这里插入图片描述

在这里插入图片描述

通过ServletContext获取web上下文信息

在这里插入图片描述

通过ServletContext实现全局数据共享

在这里插入图片描述

ServletContext对象特性

在这里插入图片描述

通过ServletContext对象获取全局参数

在这里插入图片描述

ServletConfig对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

过滤器

在这里插入图片描述

在这里插入图片描述

过滤器的使用

创建过滤器

在doFilter编写过滤业务规则,如果允许继续访问,则通过
filterChain.doFilter(servletRequest,servletResponse);
让客户端请求继续访问;如果不允许通行则可以通过servletResponse直接响应客户端(转发、重定向)。

package com.qfedu.filters;

import javax.servlet.*;
import java.io.IOException;

/**
 * @Description
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 * 1.创建一个类实现javax.servlet.Filter接口
 * 2.实现Filter接口中的init、doFilter、destroy抽象方法
 *    init 是过滤器初始化方法,用于获取过滤器的初始化参数等
 *    destory 是过滤器的销毁方法,用以释放资源
 *    doFilter 方法 用于定义过滤器的业务
 * 3.在doFilter实现过滤器业务
 */
public class MyFilter01 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("~~~~~~MyFilter01");
        //放行:运行继续执行浏览器请求的目标资源
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
    }
}

配置过滤器

配置过滤器拦截哪些服务器资源

  • xml配置
  <filter>
      <filter-name>MyFilter01</filter-name>
      <filter-class>com.qfedu.filters.MyFilter01</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFilter01</filter-name>
      <!--过滤器的拦截规则-->
      <url-pattern>/FirstServlet</url-pattern>
  </filter-mapping>  
  • 注解配置:在过滤器类添加@WebFilter注解
  • 注意/*表示拦截所有的请求
  @WebFilter("/*")
  public class MyFilter01 implements Filter {
  	//...
  }
过滤器路径配置规则

精确过滤: 配置过滤器拦截指定的请求url

例如:/FirstServlet,/index.html

后缀过滤: 配置过滤器拦截指定的后缀的请求url

例如:*.jpg 、 *.html

通配符过滤

  • /* 拦截所有请求
  • /aaa/bbb/* 拦截项目名后 demo8/aaa/bbb/FirstServlet 或者 demo8/aaa/bbb/a.html
登陆过滤器代码实现

在这里插入图片描述

代码如下:

package com.qfedu.sgms.utils;

import com.qfedu.sgms.dto.Student;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @Description 登录验证过滤器
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //1.因为此过滤器会拦截所有用户请求(包括受限资源和非受限资源)
        //  所以当一个用户请求被拦截之后,我们需要知道这个请求的路径
        // a.将ServletRequest转换成 HttpServletRequest
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // b.通过request对象获取用户的请求路径
        String uri = request.getRequestURI();    //  ----  /demo4/IndexPageServlet
        // c.截取uri最后一个/后的路径,即为请求路径
        String requestPath = uri.substring( uri.lastIndexOf("/")+1 );
        System.out.println("requestPath:"+requestPath);

        //2.判断:如果请求路径是非受限资源则直接放行,如果是受限资源则需要验证用户是否登录
        if("CheckServlet".equals(requestPath) || "login".equals(requestPath)){
            //放行
            filterChain.doFilter(servletRequest, servletResponse);
        }else{
            //进入else代码,表示此请求是受限资源,需要验证用户是否登录
            //3.判断session中是否有用户信息,如果有则表示用户已经登录——放行
            //  如果没有则表示用户未登录,转发到登录页面,提示请先登录
            HttpSession session = request.getSession();
            Student stu = (Student) session.getAttribute("stu");
            if(stu != null){
                filterChain.doFilter(servletRequest, servletResponse);
            }else{
                //转到到登录页面
                request.setAttribute("tips","请先登录!");
                request.getRequestDispatcher("login").forward(request,response);
            }
        }
    }

    @Override
    public void destroy() {

    }
}

Servlet应用

文件上传

在这里插入图片描述

案例如下

在这里插入图片描述
在这里插入图片描述

文件上传的实现

在这里插入图片描述

1.前端提交文件
  • 表单post方式提交数据

  • 设置表单的enctype=“multipart/form-data”,不对表单数据进行编码

  <!--
  当form表单数据提交时,浏览器会对表单数据进行编码,然后提交;
  当表单中存在文件的时候,要设置不编码传输
  通过form表单的enctype属性设置表单数据的压缩方式:
  - application/x-www-form-urlencoded 在发送前编码所有字符(默认)
  - text/plain 将表单数据空格转换成+,不对特殊字符进行编码
  - multipart/form-data 不对表单数据进行编码
  -->
  <form action="BookSaveServlet" method="post" enctype="multipart/form-data">
      <p>图书编号:<input type="text" name="bookId"/></p>
      <p>图书名称:<input type="text" name="bookName"/></p>
      <p>图书封面:<input type="file" name="bookImg"/></p>
      <p><input type="submit" value="提交"/></p>
  </form>
2.Servlet类接收文件
  • 在Servlet类前添加@MultipartConfig注解,赋予当前Servlet类处理未编码提交的数据的能力;

  • 通过request对象调用getPart(key)或者getParts()方法接收文件

  package com.qfedu.servlets;
  
  import javax.servlet.ServletException;
  import javax.servlet.annotation.MultipartConfig;
  import javax.servlet.annotation.WebServlet;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import javax.servlet.http.Part;
  import java.io.IOException;
  import java.util.Collection;
  
  /**
   * @Description 接收图书信息并保存
   * @Author 千锋涛哥
   * 公众号: Java架构栈
   */
  @WebServlet("/BookSaveServlet")
  @MultipartConfig
  public class BookSaveServlet extends HttpServlet {
  
      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
          doPost(request, response);
      }
  
      @Override
      protected void doPost(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
  
          //1.设置utf-8编码
          request.setCharacterEncoding("utf-8");
  
          //2.接收普通文本
  //当网页提交数据的表单设置了enctype="multipart/form-data"之后不能直接使用getParameter接收文本数据
          //需要在当前serlvet类添加 @MultipartConfig 用于处理非压缩提交的数据
          String id = request.getParameter("bookId");
          String name = request.getParameter("bookName");
  
          System.out.println("id:"+id );
          System.out.println("name:"+name );
  
          //3. 接收表单提交的图片
          // getPart("输入框name属性"): 接收表单中的文件
          Part bookImg = request.getPart("bookImg");
          System.out.println(bookImg);
          //  getParts(): 接收表单中所有文件
          //Collection<Part> parts = request.getParts();
  
          //4.保存图片
  
      }
  }
3.保存图片
  • 在web工程的web目录下新建一个files目录(保存文件的目录如果不在web服务器上,用户将无法访问)

  • files目录先放一个任意的文件(空的目录在进行项目部署的时候不会在web服务器中创建)

  //4.保存图片
  // a.获取files目录在web服务器上的路径(不是工作空间的路径)
  ServletContext servletContext = getServletContext();
  String dir = servletContext.getRealPath("/files");
  
  // b.给上传的文件重命名 (不同用户有可能上传相同名称的图片,如果不重命名将导致文件覆盖)
  //   文件重命名后缀名不能改变
  String header = bookImg.getHeader("Content-Disposition");  //form-data; name="bookImg"; filename="千锋武汉(横版).jpg"
  //   截取上传的文件的后缀名
  int begin = header.lastIndexOf(".");
  int end = header.lastIndexOf("\"");
  String ext = header.substring(begin, end);
  // 取名(时间毫秒数、UUID、雪花算法)
  String fileName  = UUID.randomUUID().toString()+ext;
  
  //c.存储文件到目录
  bookImg.write(dir+"\\"+fileName);
  
  //5.将图书信息保存到数据库: 保存到数据库的是图片的访问路径(不是绝对路径)
  Book book = new Book(id, name, "files/" + fileName);
  //调用BookDAO 将book对象保存到数据库

文件下载

在这里插入图片描述

在这里插入图片描述

案例准备工作
  • 在项目的files目录添加几个待下载的图片

  • 创建文件下载的Servlet类FileDownloadServlet

  • 创建文件列表的静态网页:在web目录下创建file-list.html

  <!DOCTYPE html>
  <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <img src="files/img01.png" height="100"/><br/>
          <a href="FileDownloadServlet?fileName=img01.png">下载</a><br/>
  
          <img src="files/img02.png" height="100"/><br/>
          <a href="FileDownloadServlet?fileName=img02.png">下载</a><br/>
  
          <img src="files/img03.png" height="100"/><br/>
          <a href="FileDownloadServlet?fileName=img03.png">下载</a><br/>
      </body>
  </html>
文件下载实现
package com.qfedu.servlets;

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.FileInputStream;
import java.io.IOException;

/**
 * @Description
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
@WebServlet("/FileDownloadServlet")
public class FileDownloadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.接收客户端传递过来的文件名(即为要下载的文件)
        String fileName = request.getParameter("fileName");  //img01.png

        //2.获取存储文件的files目录路径
        ServletContext servletContext = getServletContext();
        String dir = servletContext.getRealPath("/files");
        // 拼接要下载的文件路径
        String filePath = dir+"\\"+fileName;

        //3.设置响应头
        //设置响应的类型如果浏览器无法识别则会提示另存为
        response.setContentType("application/image"); 
        response.addHeader("Content-Disposition","attachment; fileName="+fileName);

        //4. 通过IO流将文件数据响应给浏览器(文件是二进制数据,所以获取字节流)
        ServletOutputStream outputStream = response.getOutputStream();
        // 读取服务文件,写给客户端
        FileInputStream fis = new FileInputStream(filePath);
        byte[] bs = new byte[1024];
        int len = -1;
        while( (len = fis.read(bs))!=-1){
            outputStream.write(bs,0,len);
        }
        outputStream.close();
        fis.close();
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值