request&response 使用方法

request&response

第一章-request

请求行和请求头

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

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

​ GET /day17Request/WEB01/register.htm?username=zs&password=123456 HTTP/1.1

  • getMethod();获取请求方式
  • getRemoteAddr() ;获取客户机的IP地址(知道是谁请求的)
  • getContextPath(); 获得当前应用工程名(部署的路径);
  • getRequestURI();获得请求地址,不带主机名
  • getRequestURL();获得请求地址,带主机名
  • getServerPort();获得服务端的端口
  • getQueryString();获的请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)
 	//1获取请求方式 getMethod()
        System.out.println(request.getMethod());//GET
        //2获取请求url(Uniform Resource Identifier)地址getRequestURL
        StringBuffer req1 = request.getRequestURL();
        System.out.println(req1.toString()); //http://localhost:8080/demo3
        //3获取请求的uri(Uniform Resource Locator)
        System.out.println(request.getRequestURI()); ///demo3
        System.out.println("*********************************");
       //4获取客户端的ip地址
        String remoteAddr = request.getRemoteAddr();
        System.out.println(remoteAddr); //是其他人访问则是ipv6地址
        //5获得请求所使用的协议
        System.out.println(request.getProtocol());
3.2.获得请求头信息(操作请求头)(了解)

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

img

getHeader(String name);

  • User-Agent: 浏览器信息
  • Referer:来自哪个网站(防盗链)
/**
 *
 * @author Leevi
 * 日期2020-07-12  09:14
 * 使用request获取请求头的信息
 */
@WebServlet("/demo02")
public class ServletDemo02 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //根据请求头的name获取value
        //目标:获取name为user-agent的请求头的信息
        String header = request.getHeader("user-agent");
        System.out.println("获取的请求头agent为:" + header);
    }
}

4.小结

  1. 操作请求行(获得客户机信息)
    • getMethod(); 获得请求方式
    • getRemoteAddr(); 获得客户机的IP地址
    • getContextPath(); 获得项目的部署的路径
    • getRequestURI(); 获得URI(不带http,主机,端口)
    • getRequestURL(); 获得URL(带http,主机,端口)
  2. 操作请求头
    • getHeader(String name);
      • User-Agent: 浏览器信息
      • Referer:来自哪个网站(防盗链)

获得请求参数

3.1获得请求参数
法名描述
String getParameter(String name)获得指定参数名对应的值。如果没有则返回null,如果有多个获得第一个。 例如:username=jack
String[] getParameterValues(String name)获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码
Map<String,String[]> getParameterMap()获得所有的请求参数。key为参数名,value为key对应的所有的值。
3.2 请求参数乱码处理

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

image-20191209100446323

  1. get方式, 我们现在使用的tomcat>=8.0了, 乱码tomcat已经处理好了
  2. post方式, 就需要自己处理
void setCharacterEncoding(String env); //设置请求体的编码
/**
 * 包名:${PACKAGE_NAME}
 *
 * @author Leevi
 * 日期2020-07-12  09:33
 * 使用request获取请求参数
 *
 * 请求参数的乱码问题:
 * 在tomcat8之前,无论是get请求还是post请求,请求参数都会发生乱码
 * 在tomcat8之后(包含8),只有post请求才会发生中文乱码
 *
 * 怎么解决乱码: 只要在获取请求参数之前,调用request.setCharacterEncoding(UTF-8);
 */
@WebServlet("/demo03")
public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        //1. 根据参数名,获取一个参数值
        String username = request.getParameter("username");
        //System.out.println("获取的请求参数username=" + username);

        //2. 根据参数名,获取多个参数值:比如说注册时候的兴趣爱好的复选框
        String[] hobbies = request.getParameterValues("hobby");
        /*for (String hobby : hobbies) {
            System.out.println(hobby);
        }*/

        //3. 获取所有的请求参数
        //getParameterMap()获取所有请求参数,请求参数的参数名就是map的key,请求参数的参数值就是map的value
        Map<String, String[]> parameterMap = request.getParameterMap();
        //遍历出每一个请求参数
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            String parameterName = entry.getKey();
            String[] values = entry.getValue();
            for (String value : values) {
                System.out.println("参数名:" + parameterName + ",参数值:" + value);
            }
        }
    }
}
3.3 使用BeanUtils封装

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

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

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

使用步骤:

  1. 导入jar
  2. 使用BeanUtils.populate(user,map)
  • 表单
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/requestDemo/demo04" method="post">
        用户名<input type="text" name="username"><br>
        密码<input type="text" name="password"><br>
        性别<input type="radio" name="gender" value="male"><input type="radio" name="gender" value="female"><br>
        兴趣爱好
        <input type="checkbox" name="hobby" value="basketball">篮球
        <input type="checkbox" name="hobby" value="football">足球
        <input type="checkbox" name="hobby" value="ppball">乒乓球
        <input type="checkbox" name="hobby" value="yumaoball">羽毛球
        <br>
        <input type="submit" value="注册">
    </form>
</body>
</html>
  • User
/**
 * 包名:com.itheima.pojo
 *
 * @author Leevi
 * 日期2020-07-12  10:19
 */
public class User implements Serializable {
    private String username;
    private String password;
    private String gender;
    private String[] hobby;

    public User() {
    }

    public User(String username, String password, String gender, String[] hobby) {
        this.username = username;
        this.password = password;
        this.gender = gender;
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }
}
  • ServletDemo04
/**
 * 包名:${PACKAGE_NAME}
 *
 * @author Leevi
 * 日期2020-07-12  10:18
 * 我们使用request.getParameterMap()方法获取所有请求参数,是封装在map对象中
 *
 * 我的需求是将获取到的所有请求参数封装到POJO对象中
 * 1. 创建一个POJO类,类中的属性名要和请求参数名对应
 * 2. 使用BeanUtils框架,将map中的数据封装到POJO对象中
 */
@WebServlet("/demo04")
public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        //1. 获取所有的请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        //2. 将请求参数封装到User对象中
        User user = new User();
        //3. 使用BeanUtils框架自动将map中的数据封装到对象中
        try {
            BeanUtils.populate(user,parameterMap);

            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.小结

  1. 获取请求参数的方法

    1. getParameter(name),根据参数名获取一个参数值
    2. getParameterValues(name),根据参数名获取多个参数值
    3. getParameterMap(),获取所有的请求参数封装到map中
  2. 使用BeanUtils封装

    • 如果请求参数有多个需要封装到JavaBean里面, 建议先获得Map, 再使用BeanUtils封装到JavaBean对象

    注意: JavaBean属性需要和Map的key一致 说白了也就是JavaBean属性需要和表单的name一致

  3. 解决请求参数的中文乱码问题

    1. Tomcat8之后,使用get方式提交的请求参数不会发生中文乱码
    2. 解决post请求中的中文参数乱码问题:在获取请求参数之前添加一句代码:request.setCharacterEncoding(“UTF-8”)

请求转发

request.getRequestDispatcher(url).forward(request, response);//转发

3.小结

  • 请求转发的作用:跳转页面,比如说添加完数据之后跳转到数据的展示页面,删除完数据之后跳转到展示页面
  • 请求转发的代码
request.getRequestDispatcher("转发的路径").forward(request,response); 
  • image-20211130082521707

域对象

1.目标

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

2.讲解

​ ServletContext: 范围 整个应用(无论多少次请求,只要是这个应用里面的都是可以共享的)

​ request范围: 一次请求有效

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

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

3.小结

  1. 作为域对象存取数据

    • Object getAttribute(String name) ; 取
    • void setAttribute(String name,Object object) ; 存
    • void removeAttribute(String name) ; 移除
  2. 范围: 一次请求有效(转发可以使用)

    image-20191209110018952

/**
 * 包名:${PACKAGE_NAME}
 *
 * @author Leevi
 * 日期2020-07-12  10:50
 * request作为域对象在不同的Servlet之间进行数据的共享,它只能在同一次请求中进行数据共享
 *
 * request域对象只有和请求转发一起使用才有意义
 */
@WebServlet("/demo06")
public class ServletDemo06 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 目标: 在ServletDemo07中获取ServletDemo06中的变量username的值
        // 要求只能是由ServletDemo06跳转到ServletDemo07的时候才能获取
        String username = "周杰棍";

        //将username存储到request域对象中
        request.setAttribute("name",username);

        //请求转发跳转到ServletDemo07
        request.getRequestDispatcher("/demo07").forward(request, response);
    }
}

ServletDemo07的代码

/**
 * 包名:${PACKAGE_NAME}
 *
 * @author Leevi
 * 日期2020-07-12  10:52
 */
@WebServlet("/demo07")
public class ServletDemo07 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用request域对象中取出name的值
        System.out.println("在ServletDemo07中获取username的值:"+request.getAttribute("name"));
    }
}

小结

  1. 获取请求行的信息
    1. getMethod()获取请求方式
    2. getRequestURI()获取请求的uri地址
    3. getRequestURL()获取请求的url地址
    4. getContextPath()获取项目的部署路径
    5. getRemoteAddr()获取客户端的IP地址
  2. 获取请求头的信息:getHeader(name) 掌握
  3. 获取请求参数(全部要掌握,最重要)
    1. getParameter(参数名),根据一个参数名获取一个参数值
    2. getParameterValues(参数名),根据一个参数名获取多个参数值
    3. getParameterMap()获取所有的请求参数,封装到Map中
  4. 解决请求参数乱码问题: request.setCharacterEncoding(“UTF-8”);
  5. 使用BeanUtils将map中的数据存储到JavaBean对象中(掌握)
    1. 拷贝BeanUtils的jar包,存放在WEB-INF里面的lib中
    2. map的key要和JavaBean的属性名保持一致,如果不一致那么该字段的值就无法存储
    3. BeanUtils中默认内置一些基本类型的转换器(如果map中的数据是string类型,JavaBean的属性还是int类型那么会自动转换)
  6. 使用request做请求转发: request.getRequestDispatcher(“跳转路径”).forward(request,response); 掌握
    1. 浏览器只会发送一次请求,而且浏览器的地址是跳转之前的路径
    2. 跳转操作由服务器完成的
  7. request对象作为域对象向存取数据,它的作用范围是一次请求中,和请求转发一起使用 掌握
    1. setAttribute(name,value)往域对象中存数据
    2. getAttribute(name)从域对象中获取数据

第二章-Response

操作响应行

1.目标

  • 掌握操作响应行的方法

2.讲解

HTTP/1.1 200

img/

​ 常用的状态码:

​ 200:成功

​ 302:重定向

​ 304:访问缓存

​ 404:请求路径错误

​ 500:服务器错误

3.小结

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

  2. 一般不需要设置, 可能302 重定向需要设置

  3. 常见的响应状态码

    • 200 成功
    • 302 重定向
    • 304 读缓存
    • 404 客户端错误
    • 500 服务器错误

操作响应头

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=跳转的路径"); //几秒之后跳转到指定的路径上
3.3 重定向【重点】

img/

  1. 重定向两次请求
  2. 重定向的地址栏路径改变
  3. 重定向的路径写绝对路径(带域名/ip地址的, 如果是同一个项目里面的,域名/ip地址可以省略)
  4. 重定向的路径可以是项目内部的,也可以是项目以外的(eg:百度)
  5. 重定向不能重定向到WEB-INF下的资源
  6. 把数据存到request里面, 重定向不可用
//方式一: 重定向
//1.设置状态码
//response.setStatus(302);
//2.设置重定向的路径(绝对路径,带域名/ip地址的,如果是同一个项目里面的,域名/ip地址可以省略)
//response.setHeader("Location","http://localhost:8080/day28/demo08");
//response.setHeader("Location","/day28/demo08");
//response.setHeader("Location","http://www.baidu.com");

//方式二:  直接调用sendRedirect方法, 内部封装了上面两行
response.sendRedirect("http://localhost:8080/day28/demo08");
  • 重定向
 response.sendRedirect("重定向的路径");

重定向和请求转发的对比

重定向的特点:
  1. 重定向的跳转是由浏览器发起的,在这个过程中浏览器会发起两次请求
  2. 重定向跳转可以跳转到任意服务器的资源,但是无法跳转到WEB-INF中的资源
  3. 重定向跳转不能和request域对象一起使用
  4. 重定向跳转浏览器的地址栏中的地址会变成跳转到的路径
请求转发的特点:
  1. 请求转发的跳转是由服务器发起的,在这个过程中浏览器只会发起一次请求

    1. 请求转发只能跳转到本项目的资源,但是可以跳转到WEB-INF中的资源
    2. 请求转发可以和request域对象一起使用

4.小结

4.1操作响应头

操作响应体

1.目标

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

2.步骤

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

3.讲解

操作响应体的API

img/

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

3.1 使用字符输出流输出字符串
  • 解决字符流输出中文乱码问题
response.setContentType("text/html;charset=utf-8");
  • 使用字符输出流
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;

/**
 * 包名:${PACKAGE_NAME}
 *
 * @author Leevi
 * 日期2020-07-12  12:12
 * response设置响应体的信息
 * 直接给浏览器要展示的数据
 *
 * 解决响应体的乱码问题
 * response.setContentType("text/html;charset=UTF-8");
 * 这句代码底层做了什么?
 * 1. 设置服务器响应的字符集为UTF-8
 * 2. 设置Content-Type响应头的信息为 "text/html;charset=UTF-8"
 *    让浏览器知道了服务器的响应字符集UTF-8,那么浏览器也会使用UTF-8解码
 */
@WebServlet("/demo04")
public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        //要向浏览器输出响应体的信息,需要通过流来进行操作
        //第一种:字符串,输出文本内容
        PrintWriter writer = response.getWriter();
        //使用字符流往浏览器输出文本
        //1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
        writer.write("你好世界");

        //2. print()方法,可以输出数字、字符串
        //writer.print(8);
    }
}
3.2 使用字节输出流向浏览器输出文件

目标是:向浏览器输出一张图片

注意:需要引入commons-io的jar包

/**
 * @author Leevi
 * 日期2020-07-12  14:29
 * 使用response的字节流向浏览器输出一个文件(一张图片)
 * 目标:浏览器访问ServletDemo05,会在浏览器上显示一张图片
 */
@WebServlet("/demo05")
public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 读取b.jpg图片,将其转换成字节输入流,使用ServletContext
        ServletContext servletContext = getServletContext();
        InputStream is = servletContext.getResourceAsStream("b.jpg");

        //2. 使用字节输出流,将is中的字节都输出到浏览器
        ServletOutputStream os = response.getOutputStream();

        /*byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
        }*/

        IOUtils.copy(is,os);

        os.close();
        is.close();
    }
}

response部分的总结

  1. 设置响应状态码:setStatus()
  2. 设置响应头:setHeader(name,value)
    1. refresh响应头,用于隔几秒钟之后跳转到某个页面
    2. location响应头,用于重定向到某个页面
  3. 重定向的写法: sendRedirect(地址)
  4. 设置响应体的内容
    1. 使用字符输出流输出文本内容
      1. response.getWriter()获取字符输出流
      2. writer.write()/print()输出字符串
      3. 解决响应数据的中文乱码:response.setContentType(“text/html;charset=UTF-8”)
    2. 使用字节输出流输出文件
      1. response.getOutputStream()获取字节输出流
  5. 使用IO流的框架进行边读边写

路径问题

一、完整url地址

url的组成部分:
  1. 协议 http://
  2. 服务器主机地址 localhost
  3. 服务器的端口号 :8080
  4. 项目的虚拟路径(部署路径) responseDemo
  5. 具体的项目上资源路径 /pages/hello.html 或者 /demo02 Servlet的映射路径
什么时候会使用完整的url
  1. 浏览器地址栏直接访问
  2. 一个项目中,访问另一个项目中的资源

二、相对路径

相对路径的概念

不以"/“开头的路径写法,它是以目标路径相对当前文件的路径,其中”…"表示上一级目录

它是以目标资源的url,相对当前资源的url

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>hello world....</h1>
    <!--
        目标资源的url: http://localhost:8080/responseDemo/demo05
        当前资源的url: http://localhost:8080/responseDemo/pages/demo.html

        相对路径的优劣:
            1. 优势: 无论部署的项目名怎么改变,我的路径都不需要改变
            2. 劣势: 如果当前资源的位置发生改变,那么相对路径就必定要发生改变
    -->
    <a href="../demo05">访问ServletDemo05</a>
</body>
</html>

三、绝对路径

绝对路径的概念

绝对路径就是以"/"开头的路径写法,它有如下两种情况

  1. 请求转发的绝对路径写法 “/资源的路径”,不需要写项目路径,例如"/hello.html"
  2. 不是请求转发的绝对路径写法"/项目部署路径/资源路径" 例如 “/responseDemo/hello.html”

案例-完成文件下载

1.需求分析

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

img/

2.文件下载分析

2.1什么是文件下载

​ 将服务器上已经存在的文件,输出到客户端浏览器.

​ 说白了就是把服务器端的文件拷贝一份到客户端, 文件的拷贝—> 流(输入流和输出流)的拷贝

2.2文件下载的方式
  • 第一种:超链接方式(不推荐)

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

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

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

3.思路分析

3.1超链接方式
  1. 准备下载的资源(文件)
  2. 编写一个下载页面
  3. 在这个页面上定义超链接,指定href
3.2编码方式
3.2.1手动编码方式要求

​ 设置两个头和一个流

​ 设置的两个头:

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

​ 设置一个流:

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

3.2.2思路

image-20191209150057781

4.代码实现

package com.itheima.servlet;

import org.apache.commons.io.IOUtils;

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

/**
 * @author Leevi
 * 日期2020-10-14  11:57
 * 1. 读取客户端想下载的文件
 * 2. 将客户端想下载的文件使用字节输出流的方式响应给客户端
 */
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 获取到客户端想要下载的文件名
        String fileName = request.getParameter("fileName");

        //设置下载的文件的mime-type
        String mimeType = getServletContext().getMimeType(fileName);
        response.setHeader("Content-Type",mimeType);

        //2. 使用字节输入流读取客户端要下载的那个文件
        InputStream is = getServletContext().getResourceAsStream("file/" + fileName);

        //3. 使用字节输出流,将图片输出到浏览器
        ServletOutputStream os = response.getOutputStream();

        //输出之前,我们通过设置响应头的方式,指示客户端下载文件
        //我们先将fileName进行URL编码: 使用URLEncoder
        String encodeFileName = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("Content-Disposition","attachment;filename="+encodeFileName);

        IOUtils.copy(is,os);
        os.close();
        is.close();
    }
}

5.细节处理

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

1555993058675

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

第三章-综合案例

案例-注册

1. 需求

1571732869531

2. 路径

  1. 三层结构的讲解
  2. 完成注册功能

3. 代码实现

3.1 三层架构(今天先不讲)
  • 软件中分层:按照不同功能分为不同层,通常分为三层:表现层(web层),业务层,持久(数据库)层。

    img

  • 不同层次包名的命名

分层包名(公司域名倒写)
表现层(web层)com.itheima.web
业务层(service层)com.itheima.service
持久层(数据库访问层)com.itheima.dao
JavaBeancom.itheima.bean
工具类com.itheima.utils
  • 分层的意义:
    1. 解耦:降低层与层之间的耦合性。
    2. 可维护性:提高软件的可维护性,对现有的功能进行修改和更新时不会影响原有的功能。
    3. 可扩展性:提升软件的可扩展性,添加新的功能的时候不会影响到现有的功能。
    4. 可重用性:不同层之间进行功能调用时,相同的功能可以重复使用。
  • 程序设计的宗旨:
    • 高内聚低耦合
    • 可扩展性强
    • 可维护性强
    • 可重用性强
3.2 完成注册案例
3.2.1 注册案例思路

image-20191209154418825

3.2.2准备工作
  • 数据库
create database day25;
use day25;
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;//1 表示已激活  0表示未激活
	//...
}
  • 导入jar
    • mysql驱动
    • druid
    • dbutils
    • beanutils
  • 工具类和配置文件
    • DruidUtil
    • druid.properties
3.2.3 注册案例实现

注册页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/userDemo/register" method="post">
        用户名<input type="text" name="username"><br>
        密码<input type="text" name="password"><br>
        昵称<input type="text" name="nickname"><br>
        地址<input type="text" name="address"><br>
        邮箱<input type="text" name="email"><br>
        性别<input type="radio" name="gender" value="male"><input type="radio" name="gender" value="female"><br>
        <input type="submit" value="注册">
    </form>
</body>
</html>

RegisterServlet的代码

/**
 * 包名:${PACKAGE_NAME}
 *
 * @author Leevi
 * 日期2020-07-12  16:15
 */
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //在最前面解决乱码问题:请求参数的中文乱码,响应的中文乱码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        //1. 获取所有的请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();

        //2. 使用BeanUtils 将parameterMap中的数据,存储到User对象中
        User user = new User();

        //设置默认的status为"0"
        user.setStatus("0");

        try {
            BeanUtils.populate(user,parameterMap);

            //3. 使用DBUtils将用户信息存储到数据库
            //这里需要mysql驱动、druid、dbutils的jar包
            QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
            String sql = "insert into user values (null,?,?,?,?,?,?,?)";

            queryRunner.update(sql,user.getUsername(),user.getPassword(),user.getAddress(),
                              user.getNickname(),user.getGender(),user.getEmail(),user.getStatus());

            //如果存储的时候没有出现问题,则说明注册成功,使用重定向跳转到登录页面
            response.sendRedirect("/userDemo/login.html");
        } catch (Exception e) {
            e.printStackTrace();

            //如果注册失败,则向浏览器响应一句"注册失败"
            response.getWriter().write("注册失败");
        }
    }
}

4. 小结

  1. 注册本质: 向数据库插入一条记录
  2. 思路(在RegisterServlet)
    • 获得用户提交的数据, 使用BeanUtils封装成User对象
    • 补全User对象(状态)
    • 使用DBUtils向数据库里面插入一条记录
    • 响应

案例-登录

1.需求

img

  • 点击登录按钮, 进行登录.
  • 登录成功,显示login Success
  • 登录失败,显示login failed

2.思路

image-20191209160307597

3.代码实现

3,1准备工作
  • 页面的准备 login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <form action="/userDemo/login" method="post">
        用户名<input type="text" name="username"><br>
        密码<input type="text" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>
3.2代码实现
package com.itheima.servlet;

import com.itheima.pojo.User;
import com.itheima.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

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;

/**
 * @author Leevi
 * 日期2020-10-14  14:56
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //1. 获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //2. 连接数据库校验用户名和密码
        String sql = "select * from user where username=? and password=?";
        QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
        try {
            User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
            if (user != null) {
                //登录成功
                response.getWriter().write("登录成功");
            }else {
                //登录失败
                response.getWriter().write("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().write("登录失败");
        }
    }
}

4.小结

  1. 本质: 就是根据用户名和密码查询数据库

  2. 思路(LoginServlet)

    • 获得用户输入用户名和密码
    • 使用DBUtils根据用户名和密码查询数据库 封装成User对象
    • 判断是否登录成功(判断User是否为null)
    • 响应
      equest, response);
      }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding(“UTF-8”);
    response.setContentType(“text/html;charset=UTF-8”);
    //1. 获取请求参数
    String username = request.getParameter(“username”);
    String password = request.getParameter(“password”);

     //2. 连接数据库校验用户名和密码
     String sql = "select * from user where username=? and password=?";
     QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
     try {
         User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
         if (user != null) {
             //登录成功
             response.getWriter().write("登录成功");
         }else {
             //登录失败
             response.getWriter().write("登录失败");
         }
     } catch (Exception e) {
         e.printStackTrace();
         response.getWriter().write("登录失败");
     }
    

    }
    }


### 4.小结

1. 本质: 就是根据用户名和密码查询数据库
2. 思路(LoginServlet)
   + 获得用户输入用户名和密码
   + 使用DBUtils根据用户名和密码查询数据库 封装成User对象
   + 判断是否登录成功(判断User是否为null)
   + 响应
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值