学习目标

第一章-request

知识点-request概述

1.目标

  • 知道什么是request以及作用

2.讲解

2.1什么是request

在Servlet API中,定义了一个HttpServletRequest接口,它继承自ServletRequest接口,专门用来封装HTTP请求消息。由于HTTP请求消息分为请求行、请求头和请求体三部分,因此,在HttpServletRequest接口中定义了获取请求行、请求头和请求消息体的相关方法.

img

​ Web服务器【tomcat】收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。(request对象和response对象是由Web服务器tomcat 创建的)

Request:封装请求信息,获取请求信息

Request体系结构:request-->RequstFacade-实现->HttpServletRequest-继承->ServletRequest

2.2request作用(处理请求信息)

  • 操作请求信息
  • 请求转发【资源跳转】
  • 共享数据

3.小结

  1. request:由服务器创建,传递给service方法,用于封装请求信息,获取请求信息。
  2. Request体系结构:request-->RequstFacade-实现->HttpServletRequest-继承->ServletRequest
  3. 作用
    1. 操作请求信息
    2. 转发
    3. 共享数据

知识点-操作请求行和请求头

1.目标

  • 掌握使用request对象获取客户机信息(操作请求行)和获得请求头信息(操作请求头)

2.路径

  • 获取客户机信息(操作请求行)
  • 获得请求头信息(操作请求头)

3.讲解

3.1获取客户机信息(操作请求行)

​ 请求方式 请求路径(URI) 协议版本

GET /day22/login.html?username=admin&password=123 HTTP/1.1

  • getMethod();获取请求方式
  • getRemoteAddr() ;获取客户机的IP地址(知道是谁请求的)
  • getContextPath();获得当前应用工程名(部署的路径 虚拟路径);
  • getRequestURI();获得请求地址,不带主机名和端口号
  • getRequestURL();获得请求地址,带主机名
  • getServerPort();获得服务端的端口
  • getQueryString();获得请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)
package com.itheima.web.request;

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;

@WebServlet("/request02")
public class RequestServlet02 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet02...");
        // GET  /day24/request02?username=admin&password=123   HTTP/1.1
        //1.获取请求方式get|post              String   getMethod()
        String method = request.getMethod();
        System.out.println("method = " + method);
        //2.获取资源地址uri                   String   getRequestURI()  不包含协议、ip地址、端口号
        String requestURI = request.getRequestURI();
        System.out.println("requestURI = " + requestURI);
        //3.获取请求请求路径url StringBuffer getRequestURL()   包含协议、ip地址、端口号一个完整的地址
        StringBuffer requestURL = request.getRequestURL();
        System.out.println("requestURL = " + requestURL);
        //4.获取项目虚拟路径                  getContextPath()
        String contextPath = request.getContextPath();
        System.out.println("contextPath = " + contextPath);
        //5.获取参数                         getQueryString()
        String queryString = request.getQueryString();
        System.out.println("queryString = " + queryString);
        //6.获取客户端ip地址                  getRemoteAddr()
        String remoteAddr = request.getRemoteAddr();
        System.out.println("remoteAddr = " + remoteAddr);
    }

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

3.2.获得请求头信息(操作请求头)

请求头: 浏览器告诉服务器自己的属性,配置的, 以key value存在, 可能一个key对应多个value

img

getHeader(String name);

  • User-Agent: 客户端浏览器信息
  • Referer:来自哪个网站(防盗链)
@WebServlet("/request03")
public class RequestServlet03 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet03...");
        //user-agent:获取客户端浏览器信息  方便根据浏览器的版本,解决浏览器的兼容性问题
        //referer:获取从哪里进来的  方便做防盗链处理
        String userAgent = request.getHeader("user-agent");
        System.out.println("userAgent = " + userAgent);
        String referer = request.getHeader("referer");
        System.out.println("referer = " + referer);

    }

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

4.小结

  1. 操作请求行

    1. getMethod():获取请求方式 get|post
    2. getContextPath():获取项目发布的虚拟路径
    3. getRequestURI():获取请求地址(不带协议、ip地址、端口号)
  2. 操作请求头

    1. user-agent:获取客户端浏览器的版本信息
    2. referer:获取客户端从哪一个地址进来

知识点-操作请求体(获得请求参数)【重点】

1.目标

  • 掌握获得请求参数, 以及乱码的解决

2.路径

  • 获得请求参数
  • 请求参数中文乱码的处理
  • 使用BeanUtils封装请求参数到JavaBean

3.讲解

3.1获得请求参数【通用】

法名 描述
String getParameter(String name) 获得指定参数名对应的值。如果没有则返回null,如果有多个获得第一个。 例如:username=jack
String[] getParameterValues(String name) 获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码
Map<String,String[]> getParameterMap() 获得所有的请求参数。key为参数名,value为key对应的所有的值。
@WebServlet("/request05")
public class RequestServlet05 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet05...");
        //get方式请求:不乱码  tomcat8以后已经处理好了
        //post方式请求:乱码  需要添加一句代码解决 设置服务器解析请求信息使用的字符集
        request.setCharacterEncoding("UTF-8");

        //获取请求参数   通用方法【无论是get请求还是post方式请求都可以使用】
        //getParameter():获取单个值
        //getParameterValues():获取多个值 指的是获取复选框的值
        //getRequestMap():获取所有参数封装到map集合中 参数名称作为key,参数值作为value
        String username = request.getParameter("username");
        System.out.println("username = " + username);
        String password = request.getParameter("password");
        System.out.println("password = " + password);

        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("hobby----");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }

        System.out.println("--------------------------------------------------");
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<String> keys = parameterMap.keySet();
        for (String key : keys) {
            System.out.println(key);
            String[] values = parameterMap.get(key);
            for (String value : values) {
                System.out.println(value);
            }
        }
    }

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

3.2 请求参数乱码处理

​ 我们在输入一些中文数据提交给服务器的时候,服务器解析显示出来的一堆无意义的字符,就是乱码。
那么这个乱码是如何出现的呢?如下图所示:

image-20191209100446323

  1. get方式, 我们现在使用的tomcat>=8.0了, 乱码tomcat已经处理好了
  2. post方式, 就需要自己处理
void setCharacterEncoding(String env); //设置请求体的编码
//处理post请求中文乱码
request.setCharacterEncoding("UTF-8");

乱码处理:保证编码和解码所使用的字符集一致,即可解决乱码。

3.3使用BeanUtils封装

​ 现在我们已经可以使用request对象来获取请求参数,但是,如果参数过多,我们就需要将数据封装到对象。

​ 以前封装数据的时候,实体类有多少个字段,我们就需要手动编码调用多少次setXXX方法,因此,我们需要BeanUtils来解决这个问题。

​ BeanUtils是Apache Commons组件的成员之一,主要用于简化JavaBean封装数据的操作。

使用步骤:

  1. 导入jar
  2. 使用BeanUtils.populate(user,map)
  • 表单 reg.html
<form action="request06" method="post">
    username:<input type="text" name="username"><br>
    password:<input type="password" name="password"><br>
    hobby:<input type="checkbox" name="hobby" value="sing">唱歌
            <input type="checkbox" name="hobby" value="dance">跳舞
            <input type="checkbox" name="hobby" value="code">敲代码
    <input type="submit" value="注册">
</form>
  • RequestServlet06
/**
 * 使用BeanUtils封装请求参数到javabean对象
 *  1.导入jar包
 *  2.获取所有请求参数  getParameterMap()
 *  3.创建javabean对象
 *  4.将map集合中的参数信息封装到javabean对象中 使用BeanUtils工具类的方法populate(Object obj,Map map);
 *      注意:map的key要和java对象属性一致
 */
@WebServlet("/request06")
public class RequestServlet06 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet06...");

        //解决请求中文乱码
        request.setCharacterEncoding("UTF-8");

        try {
            Map<String, String[]> parameterMap = request.getParameterMap();
            User user = new User();
            //注意:map的key要和java对象属性一致
            BeanUtils.populate(user,parameterMap);
            System.out.println("user = " + user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

4.小结

  1. 获取请求参数【通用】

    1. getParameter(String name):根据参数名称获取单个值
    2. getParameterValues(String name):根据参数名称获取多个值 用于复选框
    3. getParameterMap():获取所有请求参数封装到Map集合中
  2. 请求参数中文乱码处理

    1. get方式:没有中文乱码 无需处理 tomcat8.0版本以后已经处理了
    2. post方式:需要处理 request.setCharacterEncoding("UTF-8");
  3. 使用BeanUtils将所有请求参数map集合中的数据封装到javabean对象

    1. 导入jar包

    2. BeanUtils.populate(Object bean,Map map);

      注意:Map集合的key一定要和javabean的属性一致。

知识点-请求转发【重点】

1.目标

  • 掌握请求转发

2.讲解

请求转发:服务器内部资源跳转的一种方式

html:a标签、form表单action

js:location.href="..."

image-20210204120643731

//转发:就是将客户端的请求交给另外一个Servlet处理
//转发实现步骤
//1.获取转发对象
request.getRequestDispatcher("转发地址"); 
//2.跳转
forward(request,response);

//经常就一步完成
request.getRequestDispatcher("转发地址").forward(request,response);

RequestServlet07.java

/**
 * 转发
 */
@WebServlet("/request07")
public class RequestServlet07 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet07...");

        //共享数据
        request.setAttribute("rkey","rrr");

        //转发实现 相对路径
        request.getRequestDispatcher("request08").forward(request,response);

        //转发实现 绝对路径   服务器端使用/:表示http://localhost:8080/虚拟路径
        //request.getRequestDispatcher("/request08").forward(request,response);

        //转发不能访问到外部资源
        //request.getRequestDispatcher("https://www.baidu.com").forward(request,response);
        //转发可以访问到WEB-INF下的资源
        //request.getRequestDispatcher("WEB-INF/haha.html").forward(request,response);
    }

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

RequestServlet08.java

package com.itheima.web.request;

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;

/**
 * 转发
 */
@WebServlet("/request08")
public class RequestServlet08 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet08...");
        //转发一次请求  可以使用Request对象共享数据
        Object rkey = request.getAttribute("rkey");
        System.out.println(rkey);
    }

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

特点:

	1.	转发发生在服务器内部,不能请求外部资源
	2.	转发地址栏不发生改变
	3.	转发发送一次请求
	4.	转发一般使用相对路径
	5.	转发请求数据不会丢失
	6.	转发可以访问到WEB-INF下的资源

3.小结

  • 转发 :指的是将客户端的请求,服务端接收之后再交给第三方处理,是一种服务器内部资源跳转方式。

  • 实现:request.getRequestDispacther("转发地址").forward(request,response);

  • 特点:

    • 1.转发只发送一次请求,转发地址栏不发生改变
      2.转发请求信息不会丢失
      3.转发只能请求服务器内部【当前web应用】资源,不能请求外部资源
      4.转发可以请求WEB-INF下的资源
      5.转发使用的是相对路径
      

知识点-作为域对象存取值

1.目标

  • 掌握request作为域对象存取值

2.讲解

​ ServletContext:域对象 代表的是整个应用

域对象:一个有作用范围的对象 ,在它的作用范围中可以实现数据共享。

request域对象:一次请求,因此一般只能在转发中使用数据共享

​ 域对象是一个容器,这种容器主要用于Servlet与Servlet/JSP之间的数据传输使用的。

  • Object getAttribute(String name) ;
  • void setAttribute(String name,Object object) ;
  • void removeAttribute(String name) ;

3.小结

  1. request域对象:在一次请求中共享数据,只能用在转发中

  2. API

    • setAttribute(String name,Object value);
    • getAtrribute(String name);
    • removeAttribute(String name);

第二章-Response

知识点-Response概述

1.目标

  • 掌握什么是Response,以及Response的作用

2.讲解

2.1HttpServletResponse概述

​ Response:封装响应信息,响应给客户端浏览器

​ 体系结构:response-->RequestFacade-实现->HttpServletResponse-继承->ServletResponse

​ 在Servlet API中,定义了一个HttpServletResponse接口(doGet,doPost方法的参数),它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为响应行、响应头、响应体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应头、响应体的方法

2.2作用

  • 设置响应的三部分(响应行,响应头,响应体)

3.小结

  1. Response:封装响应信息,设置响应信息 响应给客户端浏览器
  2. 体系结构:ServletResponse--继承-->HttpServletResponse--实现-->ResponseFacade
  3. tomcat创建了request和response对象,开发中只需要使用这两个对象即可,使用request对象获取请求信息,使用response对象设置响应信息。
  4. 作用:设置响应内容

知识点-操作响应行

1.目标

  • 掌握操作响应行的方法

2.讲解

响应行
HTTP/1.1  200
响应头
响应体

img/

​ 常用的状态码:

​ 200:请求成功

​ 404:请求资源不存在 【请求地址写错】

​ 500:服务器内部错误 【java代码报错】

​ 302:重定向

​ 304:读取缓存数据

​ 403:请求禁止 没有权限访问

​ 406:请求和响应的内容不一致

3.小结

  1. 设置的API: response.setStatus(int code);

  2. http状态码

    1. 200:成功
    2. 404:请求资源不存在
    3. 500:服务器内部错误

知识点-操作响应头【重点】

1.目标

  • 掌握操作响应头的方法, 能够进行定时刷新和重定向

2.路径

  • 操作响应头的API介绍
  • 定时刷新
  • 重定向

3.讲解

3.1操作响应头的API

响应头: 是服务器指示浏览器去做什么

​ 一个key对应一个value

img/

​ 一个key对应多个value

img/

关注的方法: setHeader(String name,String value);

​ 常用的响应头

​ Refresh:定时跳转 (eg:服务器告诉浏览器5s之后跳转到百度)

​ Location:重定向地址(eg: 服务器告诉浏览器跳转到xxx)

​ Content-Disposition: 告诉浏览器下载

​ Content-Type:设置响应内容的MIME类型(服务器告诉浏览器内容的类型)

3.2定时刷新

response.setHeader("refresh","秒数;url=跳转的路径"); //几秒之后跳转到指定的路径上

response.setHeader("refresh","5; url=http://www.baidu.com");

3.3 重定向【重点】

image-20210204145838502

img/

response.sendRedirect("demo09");
package com.itheima.web.response;

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;

/**
 * 重定向 客户端请求response02,被重定向到response03
 */
@WebServlet("/response02")
public class ResponseServlet02 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ResponseServlet02...");
        //重定向实现方式一:
        //设置响应码
        //response.setStatus(302);
        //设置响应头
        //response.setHeader("location","response03");

        //重定向实现方式二: response.sendRedirect("新的地址");
        //response.sendRedirect("response03");

        //重定向访问外部资源
        //response.sendRedirect("http://www.baidu.com");

        //使用绝对路径重定向
        response.sendRedirect("/day23/response03");

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
  • 重定向
 response.sendRedirect("重定向的路径");

特点:

1.  重定向地址栏发送改变
2.  重定向发生了两次请求
3.  重定向不能访问WEB-INF下的资料,并且请求数据会丢失
4.  重定向可以访问外部资源
5.  重定向一般使用绝对路径,如果是同一个项目内的资源,可以使用相对路径。

4.小结

4.1操作响应头

response.setHeader(String name,String value)

4.2重定向

​ 重定向 :服务端让客户端重新发送一次请求

​ 实现:response.sendRedirect("重定向地址");

​ 转发和重定向的区别 【forward和redirect的区别?】:

	1.	转发发送一次请求,地址栏不发生改变;重定向发送两次请求,地址栏发送改变
	2.	转发请求信息不会丢失;重定向请求信息会丢失
	3.	转发只能请求服务器内部资源;重定向既可以请求服务器内部资源,又可以请求外部资源
	4.	转发可以访问WEB-INF下的资源;重定向不行
	5.	转发一般使用相对路径,重定向使用一般使用绝对路径

知识点-相对路径和绝对路径

讲解

​ 相对路径:有参照物,根据当前位置进行参照选择资源

​ ./:当前位置

​ ../:上一级目录

eg:
index.html:<a href="request05">转发</a><br>         :相对的就是当前页面 【静态资源】
ResponseDemo01:response.sendRedirect("response02"); :相对的是当前Servlet地址  【动态资源】

​ 绝对路径:直接通过地址定位唯一资源

​ 1. 以盘符开头的:D:\czbk\java119\day24-request&response

​ 2. 以Http开头的:http://localhost:8080/day24/WEB-INF/a.html

相对路径
   index.html:http://localhost:8080/day24/index.html
   response01:http://localhost:8080/day24/response01
   所以:这里 我从index.html页面跳转到response01的Servlet  使用相对路径 直接写response01就可以了

路径跳转加/: /表示的是绝对路径
    前端加/: /加在前端代表的是服务器的地址:http://localhost:8080
    后台加/: 注意这个地址给谁用:
    		 如果是服务器使用【转发】,表示的就是当前应用地址:http://localhost:8080/day24
             如果是给客户端用【重定向】,表示的就是服务器的地址:http://localhost:8080

一般情况下,项目中建议使用相对路径。

知识点-操作响应体

1.目标

  • 掌握操作响应体以及响应乱码的解决

2.步骤

  • 操作响应体的API介绍
  • 响应乱码的解决

3.讲解

3.1操作响应体的API

img/

​ 页面输出只能使用其中的一个流实现,两个流是互斥的.

3.2响应乱码处理

  • 解决字符流输出中文乱码问题
response.setContentType("text/html;charset=utf-8");
  • 使用字节输出流输出中文乱码问题
//设置浏览器打开方式
response.setHeader("Content-type", "text/html;charset=utf-8");
//得到字节输出流
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write("你好".getBytes("utf-8"));// 使用平台的默认字符(utf-8)集将此 String 编码为 byte 序列
package com.itheima.web.response;

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.IOException;

/**
 * 操作响应体
 */
@WebServlet("/response04")
public class ResponseServlet04 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ResponseServlet04...");
        //设置响应内容的字符编码集
        //response.setCharacterEncoding("UTF-8");

        //服务器直接告诉浏览器我给你响应的内容 你应该使用什么字符集编码解析
        response.setContentType("text/html;charset=UTF-8");

        //以字符流的方式向客户端浏览器输出内容
        //response.getWriter().print("Hello SZ118");
        //response.getWriter().print("中国威武!");

        //以字节流的方式向客户端浏览器输出内容
        ServletOutputStream outputStream = response.getOutputStream();
        //outputStream.write("Hello World!".getBytes());
        outputStream.write("打倒小日本!".getBytes("UTF-8"));
    }

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

4.小结

  1. 操作响应体
    1. 字符流输出:response.getWriter().print("...");
    2. 字节流输出:response.getOutPutStream.write(byte[]);
  2. 响应中文乱码
    1. 原因:内容在编码和解码时使用的字符编码集不一致导致。
    2. 解决:response.setContentType("text/html;charset=UTF-8");

案例-完成文件下载

1.需求分析

  • 创建文件下载的列表的页面,点击列表中的某些链接,下载文件.

img/

2.文件下载分析

2.1什么是文件下载

​ 将服务器上已有的文件拷贝到本地(客户端)

​ IO流操作 response.getOutputStream()向客户端写入流

2.2文件下载的方式

  • 第一种:超链接方式(不推荐)

    链接的方式:直接将服务器上的文件的路径写到href属性中.如果浏览器不支持该格式文件,那么就会提示进行下载保存, 如果浏览器支持这个格式(eg: png, jpg....)的文件,那么直接打开,不再下载了

  • 第二种:手动编码方式(推荐)

    手动编写代码实现下载.无论浏览器是否识别该格式的文件,都会下载.

3.思路分析

3.1超链接方式

  1. 准备下载资源
  2. 编写下载页面 编写a标签
  3. 浏览器访问下载

3.2编码方式

3.2.1手动编码方式要求

​ 设置两个头和一个流

​ 设置的两个头:

Content-Dispostion: 服务器告诉浏览器去下载

Content-Type: 告诉浏览器文件类型.(MIME的类型)

​ 设置一个流:

获得要下载的文件的输入流.

3.2.2思路
  1. 处理请求响应中文乱码
  2. 获取要下载的文件名称
  3. 使用ServletContext对象获取要下载文件的字节输入流
  4. 设置响应头,告诉浏览器执行下载操作
  5. 设置响应头,告诉浏览器要下载的文件类型
  6. 使用response以字节流的方式将下载文件内容输出到客户端浏览器

4.代码实现

package com.itheima.web.response;

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;
import java.io.InputStream;
import java.net.URLEncoder;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.处理请求响应中文乱码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        // 1.获取请求参数  【要下载的文件名称】
        String filename = request.getParameter("filename");
        // 2.获取要下载文件的字节输入流
        InputStream inputStream = this.getServletContext().getResourceAsStream("download/" + filename);
        // 3.设置响应头  告诉浏览器你要下载
        //防止下载文件 文件名称中文乱码显示不正常 所以对文件名进行编码 
        //目前主流浏览器默认的编码解码方式使用的是UTF-8
        System.out.println("编码前:"+filename);
        filename = URLEncoder.encode(filename,"UTF-8");
        System.out.println("编码后:"+filename);

        response.setHeader("Content-Disposition","attachment;filename="+filename);
        // 4.设置响应头  告诉浏览器 我给你下载的文件类型
        String mimeType = this.getServletContext().getMimeType(filename);
        response.setHeader("Content-Type",mimeType);
        // 5.使用response将文件的字节输入流输出到客户端浏览器
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int i = -1;
        while((i=inputStream.read(b))!=-1){
            outputStream.write(b,0,i);
        }
        inputStream.close();
    }

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

5.细节处理

  • 告诉浏览器设置的响应头里面不支持中文的, 抓包来看:

1555993058675

  • 解决方案: 手动进行编码再设置进去就ok了

    filename = URLEncoder.encode(filename,"UTF-8");

第三章-综合案例

案例-注册

1. 需求

1571732869531

说白了:就是向数据库中插入一条用户记录

2. 路径

  1. 完成注册功能

3. 代码实现

3.2 完成注册案例

3.2.1准备工作
  • 数据库
create database day24;
use day24;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(40) DEFAULT NULL,
  `password` varchar(40) DEFAULT NULL,
  `address` varchar(40) DEFAULT NULL,
  `nickname` varchar(40) DEFAULT NULL,
  `gender` varchar(10) DEFAULT NULL,
  `email` varchar(20) DEFAULT NULL,
  `status` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
  • JavaBean
public class User implements Serializable{
    private Integer id;
    private String username;
    private String password;
    private String address;
    private String nickname;
    private String gender;
    private String email;
    private String status;
	//...
}
  • 导入jar
  • 工具类和配置文件
  • register.html
3.2.2 注册案例思路

image-20210526163850807

3.2.3 注册案例实现
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //0.中文乱码处理
            request.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            // 1.获取请求参数【注册用户信息】
            Map<String, String[]> parameterMap = request.getParameterMap();
            // 2.使用BeanUtils将参数封装到user对象中  map的key要和java对象的属性一致
            User user = new User();
            BeanUtils.populate(user,parameterMap);
            // 3.将注册用户信息插入到数据库
            QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
            String sql = "insert into user values(null,?,?,?,?,?,?,?)";
            int rows = queryRunner.update(sql,user.getUsername(),user.getPassword(),user.getAddress(),user.getNickname(),user.getGender(),user.getEmail(),user.getStatus());
            // 4.响应 根据插入数据返回的受影响的行数判断
            // 如果rows>0 注册成功// 否则  注册失败
            if(rows>0){
                response.getWriter().print("注册成功!");
            }else{
                response.getWriter().print("注册失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().print("服务器异常!");
        }
    }

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

4. 小结

  1. 注册:本质就是向数据库中插入一条数据
  2. 思路:
    1. 获取请求参数
    2. 将注册信息插入数据库
    3. 根据处理结果进行响应

案例-登录

1.需求

img

  • 点击登录按钮, 进行登录. 查询数据库中是否存在对应的一条记录!
  • 登录成功,显示login Success
  • 登录失败,显示login failed

2.思路

image-20210526170030557

3.代码实现

3,1准备工作

  • 页面的准备 login.html
<!DOCTYPE html>
<html lang="en">
<head>
    
    <title>Title</title>
</head>
<body>
<center>
    <h1>用户登录</h1>
    <form action="login" method="post">
        姓名:<input type="text" name="username"/><br/>
        密码:<input type="password" name="password"/><br/>
        <input type="submit" value="登录"/>
    </form>
</center>
</body>
</html>

3.2代码实现

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            request.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            //1.获取请求参数【用户名和密码】
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            //2.查询数据库 返回user对象
            QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
            String sql = "select * from user where username=? and password=?";
            User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
            //3.响应 user!=null表示用户存在 登录成功 ;user==null表示用户不存在 登录失败
            if(user!=null){
                response.getWriter().print("登录成功!");
            }else{
                response.getWriter().print("登录失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().print("服务器异常!");
        }

    }

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

4.小结

  1. 登录:根据用户名和密码去查询数据库 看是否存在一条用户记录
  2. 思路:
    1. 获取请求参数
    2. 根据用户名密码查询数据库
    3. 根据返回的user对象 user==null 表示登录失败 user!=null 表示登录成功

总结

  1. request

    1. 概念:request用来封装请求信息

    2. 体系结构:HttpServletRequest-继承->ServletRequest

    3. request对象来源:由服务器tomcat创建并传入Servlet

    4. 作用:操作请求信息、请求转发、作为域对象存储数据

    5. 操作请求行

      // 获取请求方式  get|post
      request.getMethod();
      // 获取请求地址URI(不包含主机ip地址和端口号)
      request.getRequestURI();
      // 获取项目的虚拟路径  eg:/day24
      request.getContextPath();
      
    6. 操作请求头

      // 获取客户端浏览器信息  为了解决浏览器兼容性
      request.getHeader("User-Agent");
      // 获取进入当前资源的上一个地址  作用:防盗链
      request.getHeader("Referer");
      
    7. 操作请求体【获取请求参数 重点】

      // 获取单个值
      request.getParameter("name属性值");
      // 获取多个值
      request.getParameterValues("name属性值");
      // 获取全部请求参数 并封装到Map集合  参数名称作为key 参数值作为value
      request.getParameterMap();
      
      // 请求中文乱码处理
      request.setCharacterEncoding("UTF-8");
      // 使用BeanUtils封装请求信息到javabean
      BeanUtils.populate(javabean名称,参数map集合);
      
    8. 请求转发

      request.getRequestDispatcher("转发的地址").forward(request,response);
      
    9. 作为域对象存储数据

      // request域对象存储数据有效范围:一次请求中
      // 使用场景:转发中使用
      //存
      request.setAttribute(String key,Object value);
      //取
      request.getAttribute(String key);
      //删
      request.removeAttribute(String key);
      
  2. response

    1. response:封装响应信息

    2. 体系结构:HttpServletResponse-继承->ServletResponse

    3. response来源:由服务器tomcat创建 并传入到Servlet中

    4. 作用:操作响应信息

    5. 操作响应行 setStatus(int statusCode);

    6. 操作响应头

      // 定时刷新
      response.setHeader("Refresh","5; url=http://www.baidu.com");
      // 重定向
      response.sendRedirect("重定向的地址");
      // 告诉浏览器下载
      response.setHeader("Content-Disposition","attachment;filename="+filename);
      // 告诉浏览器下载的文件类型
      response.setHeader("content-type",mimeType);
      
    7. 操作响应体

      // 处理响应中文乱码
      response.setContentType("text/html;charset=UTF-8");
      
      // 输出字符流到客户端浏览器
      response.getWriter.print("输出内容");
      // 输出字节流到客户端浏览器
      response.getOutputStream.write("输出内容");
      
posted on 2022-04-24 23:09  ofanimon  阅读(32)  评论(0编辑  收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css