JavaWEB(下)

WEB服务器

什么是WEB服务器

JavaWEB(下)_第1张图片

静态资源和动态资源

JavaWEB(下)_第2张图片

常用的服务器产品

JavaWEB(下)_第3张图片

Tomcat简介

JavaWEB(下)_第4张图片
JavaWEB(下)_第5张图片
JavaWEB(下)_第6张图片

Tomcat的启动和关闭

在这里插入图片描述
JavaWEB(下)_第7张图片

web项目部署

JavaWEB(下)_第8张图片

浏览器访问WEB服务器

JavaWEB(下)_第9张图片

Tomcat服务器请求响应流程

JavaWEB(下)_第10张图片
JavaWEB(下)_第11张图片

HTTP协议

JavaWEB(下)_第12张图片
JavaWEB(下)_第13张图片
JavaWEB(下)_第14张图片

HTTP协议通信规则

JavaWEB(下)_第15张图片

HTTP请求规则

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

JavaWEB(下)_第16张图片

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响应内容

JavaWEB(下)_第17张图片

HTTP响应状态码

JavaWEB(下)_第18张图片

Servlet

Servlet简介

JavaWEB(下)_第19张图片

JavaWeb工程

JavaWEB(下)_第20张图片
JavaWEB(下)_第21张图片
JavaWEB(下)_第22张图片
JavaWEB(下)_第23张图片
javaweb 工程目录
JavaWEB(下)_第24张图片

创建Servlet

JavaWEB(下)_第25张图片

配置servlet

JavaWEB(下)_第26张图片

基于web.xml配置servlet

JavaWEB(下)_第27张图片

基于注解配置Servlet

JavaWEB(下)_第28张图片

IDEA部署WEB项目

JavaWEB(下)_第29张图片
如果创建项目的时候已经配置了,web服务器者可以直接按照上面的步骤执行即可,如果没有配置服务器则需要按照下面的方法配置服务器

配置服务器

JavaWEB(下)_第30张图片
JavaWEB(下)_第31张图片
JavaWEB(下)_第32张图片
JavaWEB(下)_第33张图片
JavaWEB(下)_第34张图片
然后下面的步骤就和上面的第一种情况一致

浏览器访问测试

通过浏览器发送请求,访问tomcat中web项目的servlet类
JavaWEB(下)_第35张图片

GET请求和POST请求

GET提交

JavaWEB(下)_第36张图片
JavaWEB(下)_第37张图片

POST提交

JavaWEB(下)_第38张图片
JavaWEB(下)_第39张图片

Servlet响应动态网页案例

JavaWEB(下)_第40张图片

实现代码:

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("");
        out.println("");
        out.println("这是Servlet响应的网页");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("
图书编号图书名称图书作者图书价格图书封面
"+book.getBookId()+""+book.getBookName()+""+book.getBookAuthor()+""+book.getBookPrice()+""+book.getBookImgPath()+"
"
); out.println(""); out.println(""); out.flush(); out.close(); } }

Servlet动态请求与核心类接口

JavaWEB(下)_第41张图片

Servlet类处理用户请求的流程

JavaWEB(下)_第42张图片

Servlet实例的生命周期

JavaWEB(下)_第43张图片
JavaWEB(下)_第44张图片

Servlet线程安全问题

JavaWEB(下)_第45张图片

Servlet开发技术

JavaWEB(下)_第46张图片
JavaWEB(下)_第47张图片
也就是说我们向服务器发送的请求会被封装成一个对象,所以我们下面要学的就是如何从这个对象中获取我们想要的信息

获取请求行的数据

JavaWEB(下)_第48张图片
JavaWEB(下)_第49张图片

获取请求头中的数据

JavaWEB(下)_第50张图片

JavaWEB(下)_第51张图片

获取请求正文中的数据

JavaWEB(下)_第52张图片
JavaWEB(下)_第53张图片

request对象常用方法

JavaWEB(下)_第54张图片
JavaWEB(下)_第55张图片

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对象处理上面案例中提交中文乱码问题

JavaWEB(下)_第56张图片
JavaWEB(下)_第57张图片
JavaWEB(下)_第58张图片

通过httpServletResponse对象来响应http请求

JavaWEB(下)_第59张图片

学生成绩查询案例

JavaWEB(下)_第60张图片

项目环境搭建

JavaWEB(下)_第61张图片

JavaWEB(下)_第62张图片
JavaWEB(下)_第63张图片

相应的环境搭建代码:
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. 转发跳转流程

JavaWEB(下)_第64张图片

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发送请求。

JavaWEB(下)_第65张图片

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

状态管理

JavaWEB(下)_第66张图片

状态管理实现

JavaWEB(下)_第67张图片

JavaWEB(下)_第68张图片

cookie的使用

JavaWEB(下)_第69张图片

JavaWEB(下)_第70张图片

案例如下:
JavaWEB(下)_第71张图片
JavaWEB(下)_第72张图片

代码如下:
JavaWEB(下)_第73张图片

-创建两个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("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("");
        out.println("请求SecondServlet");
        out.println("");
        out.println("");
        out.println("");
        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对象

JavaWEB(下)_第74张图片

JavaWEB(下)_第75张图片
session的原理
在这里插入图片描述

JavaWEB(下)_第76张图片
JavaWEB(下)_第77张图片
注意上面所有的过程都是由服务器和浏览器自动完成

获取session对象

JavaWEB(下)_第78张图片

session对象数据操作

JavaWEB(下)_第79张图片

session对象失效

JavaWEB(下)_第80张图片
JavaWEB(下)_第81张图片
JavaWEB(下)_第82张图片
JavaWEB(下)_第83张图片

request与session的区别

在这里插入图片描述
JavaWEB(下)_第84张图片

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

JavaWEB(下)_第85张图片
session中数据间可以流通的方式

JavaWEB(下)_第86张图片

ServletContext对象

JavaWEB(下)_第87张图片

JavaWEB(下)_第88张图片

通过ServletContext获取web上下文信息

通过ServletContext实现全局数据共享

JavaWEB(下)_第89张图片

ServletContext对象特性

JavaWEB(下)_第90张图片

通过ServletContext对象获取全局参数

JavaWEB(下)_第91张图片

ServletConfig对象

JavaWEB(下)_第92张图片
JavaWEB(下)_第93张图片
JavaWEB(下)_第94张图片

过滤器

JavaWEB(下)_第95张图片

JavaWEB(下)_第96张图片

过滤器的使用

创建过滤器

在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>MyFilter01filter-name>
      <filter-class>com.qfedu.filters.MyFilter01filter-class>
  filter>
  <filter-mapping>
      <filter-name>MyFilter01filter-name>
      
      <url-pattern>/FirstServleturl-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

登陆过滤器代码实现

JavaWEB(下)_第97张图片

代码如下:

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应用

文件上传

在这里插入图片描述

案例如下

JavaWEB(下)_第98张图片
JavaWEB(下)_第99张图片

文件上传的实现

JavaWEB(下)_第100张图片

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

  • 设置表单的enctype=“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 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对象保存到数据库

文件下载

在这里插入图片描述

JavaWEB(下)_第101张图片

案例准备工作

  • 在项目的files目录添加几个待下载的图片

  • 创建文件下载的Servlet类FileDownloadServlet

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

  DOCTYPE html>
  <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
      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();
    }
}

你可能感兴趣的:(Javaweb,java,tomcat)