request&response

一.request

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

在这里插入图片描述

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

request作用
  • 操作请求三部分(行,头,体)
  • 请求转发 . 转发这个请求给别人
  • 作为域对象存数据 像ServletContext一样,存|取数据

操作请求行和请求头

1.获取客户机信息(操作请求行)
  • getMethod();获取请求方式

  • getRemoteAddr() ;获取客户机的IP地址(知道是谁请求的)

  • getContextPath();获得当前应用工程名(部署的路径);

  • getRequestURI();获得请求地址,不带主机名

  • getRequestURL();获得请求地址,带主机名

  • getServerPort();获得服务端的端口

  • getQueryString();获的请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)

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

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

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

getHeader(String name);

  • User-Agent: 浏览器信息
  • Referer:来自哪个网站(防盗链)
package com.itheima._02_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;
import java.util.Enumeration;

/*
 *  @描述: 通过request对象,获取请求行 和 请求头
 */
@WebServlet("/request01")
public class _01_request extends HttpServlet{


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

        //1. 获取请求行  GET   www.baidu.com   http/1.1
        //http://localhost:8080/day25_request_response/request01


        //method=GET
        String method = req.getMethod();
        System.out.println("method=" + method);


        //uri=/day25_request_response/request01
        String uri = req.getRequestURI();
        System.out.println("uri=" + uri);

        //url=http://localhost:8080/day25_request_response/request01
        StringBuffer url = req.getRequestURL();
        System.out.println("url=" + url);


        //protocol=HTTP/1.1
        String protocol = req.getProtocol();
        System.out.println("protocol=" + protocol);


        System.out.println("\n=-------------------------------------\n");

        //2. 可以获取请求头
        String ua = req.getHeader("User-Agent");
        System.out.println("ua=" + ua);


//        req.getHeaderNames()  获取所有的头名字
//        req.getHeader("头的名字")  获取单个头的值
//        req.getHeaders("头的名字")  头可能有多个值,所以用这种方法

        Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String header = headerNames.nextElement();
            String value = req.getHeader(header);
            System.out.println(header + "=" + value);
        }
    }
}

操作请求体(获得请求参数)

1.获得请求参数
法名描述
String getParameter(String name)获得指定参数名对应的值。如果没有则返回null,如果有多个获得第一个。 例如:username=jack
String[] getParameterValues(String name)获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码
Map<String,String[]> getParameterMap()获得所有的请求参数。key为参数名,value为key对应的所有的值。
package com.itheima._02_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;
import java.util.Map;

/*
 *  @描述:    通过request对象,获取请求体
 */
@WebServlet("/request02")
public class _02_request extends HttpServlet{


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取单个参数
        String username = req.getParameter("username");
        System.out.println("username=" + username);

        //2. 获取所有的参数
        Map<String, String[]> map = req.getParameterMap();
        for(Map.Entry<String , String[]> entry : map.entrySet()){

            String key = entry.getKey();

            //因为有的参数可以有多个值,比如:爱好就可以传递多个值过来
            String [] value = entry.getValue();

            //一般来说只有一个,所以这里直接取0位置。如果有多个值,得遍历了。
            System.out.println(key + "=" + value[0]);
        }
    }
}
2.请求参数乱码处理

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

  1. get方式, 我们现在使用的tomcat>=8.0了, 乱码tomcat已经处理好了
  2. post方式, 就需要自己处理
package com.itheima._02_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;

/*
 *  @描述:    通过request对象,获取请求体
 *              执行post请求,携带中文数据。
 */
@WebServlet("/request03")
public class _03_request extends HttpServlet{

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

        //在取数据之前,先告诉servlet用什么编码去取数据
        //如果不设置,默认取值的时候,采用iso-8859-1的编码取值。这肯定就有乱码了。
        req.setCharacterEncoding("UTF-8");


        String username = req.getParameter("username");
        System.out.println("username=" + username);

        String password = req.getParameter("password");
        System.out.println("password=" + password);

    }
}

3.使用BeanUtils封装

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

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

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

使用步骤:

  1. 导入jar

commons-beanutils-1.8.3.jar 和 commons-logging-1.1.1.jar

  1. 使用BeanUtils.populate(user,map)
package com.itheima._02_request;

import com.itheima.bean.User;
import org.apache.commons.beanutils.BeanUtils;

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.lang.reflect.InvocationTargetException;
import java.util.Map;

/*
 *  @描述:    获取到参数之后,打包成一个对象。
 */
@WebServlet("/request04")
public class _04_request extends HttpServlet{


    //这个doGet方法不会执行,如果执行的请求方式是post
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       /* //1. 获取数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String address = req.getParameter("address");
        String phone = req.getParameter("phone");

        //2. 封装对象
        User user = new User(username , password , address , phone);
        System.out.println("user=" + user);

        */

        try {
            //1. 获取参数 还有一些特殊的地方,爱好,,有三个数据,???
            Map<String, String[]> map = req.getParameterMap();

            //2. 创建对象
            User u = new User();

            //3. 把参数封装到对象身上
            BeanUtils.populate(u , map);

            //4. 打印一下
            System.out.println("u=" + u);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
  • 如果请求参数有多个需要封装到JavaBean里面, 建议先获得Map, 再使用BeanUtils封装到JavaBean对象

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

请求转发forward

  • 请求转发的本质就是: 跳转 ,不能跳转到外部的资源,只能跳转到项目内部的资源
request.getRequestDispatcher(url).forward(request, response);  //转发
package com.itheima._02_request._02;

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;

/*
 *  @描述:    TODO
 */
@WebServlet("/request0201")
public class _01_request  extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest requset, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("来了一个get请求2...");

        //处理完请求,可以让请求跳转到别的地方去。可以跳转一个页面,可以跳转到网站。

        //外面的资源路径,跳转不了
        //req.getRequestDispatcher("http://www.baidu.com").forward(req ,resp);

        //跳转到项目自己内部的资源
        //requset.getRequestDispatcher("login.html").forward(requset,response);
        requset.getRequestDispatcher("/WEB-INF/register.html").forward(requset,response);
    }
}

  • 请求的路径不会变化
  • 一次请求
  • 转发可以转发到WEB-INF里面的资源 (WEB-INF的资源,不能直接访问,可以通过servlet进行跳转访问)

作为域对象存取值

​ ServletContext: 可以存|取值,范围是整个应用程序, AServlet 存值, BServlet能取值

​ request范围: 一次请求内有效!!!

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

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

FirstServlet

package com.itheima._02_request._03;

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;

/*
 *  @创建时间:  2020/7/28 11:54
 *  @描述:    request存值和取值
 */
@WebServlet("/first")
public class FirstServlet  extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //存值
        req.setAttribute("username" , "张三");


        //自己取值
        String username = (String) req.getAttribute("username");
        System.out.println("FirstServlet::username=" + username);;


        System.out.println("first::hashcode" + req.hashCode());
        System.out.println("使用请求转发跳转到SecondServlet" );
        //使用请求转发的方式跳转到SecondServlet
        req.getRequestDispatcher("second").forward(req,resp);
    }
}


SecondServlet

package com.itheima._02_request._03;

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;

/*
 *  @创建时间:  2020/7/28 11:54
 *  @描述:    request存值和取值
 */
@WebServlet("/second")
public class SecondServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("second::hashcode" + req.hashCode());
        //取值
        String username = (String) req.getAttribute("username");
        System.out.println("SecondServlet::username=" + username);;

    }
}


在这里插入图片描述

二.Response

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

  1. Response代表响应对象. 原型是HttpServletResponse, 服务器(Tomcat)创建的, 以形参的形式存在doGet()/doPost()方法
  2. Response的作用
    • 操作响应的三部分(行, 头, 体)

操作响应行

HTTP/1.1 200

在这里插入图片描述

​ 常用的状态码:

​ 200:成功

​ 302:重定向

​ 304:访问缓存

​ 404:客户端错误

​ 500:服务器错误

操作响应头

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

​ 一个key对应一个value

在这里插入图片描述

​ 一个key对应多个value

在这里插入图片描述

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

​ 常用的响应头

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

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

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

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

1.定时刷新
package com.itheima._03_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;

/*
 *  @描述:    TODO
 */

@WebServlet("/response01")
public class _01_response  extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        System.out.println("来了一个请求");

        //给人家反馈

        //1. 设置响应行 http/1.1 200
        //resp.setStatus(404);
        //resp.setStatus(500 , "Internal server error");

        //设置响应头  告诉浏览器过5秒钟之后,打开指定的网址。
        resp.setHeader("Refresh" , " 5; url=http://www.itheima.com");
    }
}


2. 重定向–跳转

在这里插入图片描述

  1. 重定向两次请求
  2. 重定向的地址栏路径改变
  3. 重定向的路径写绝对路径(带域名/ip地址的, 如果是同一个项目里面的,域名/ip地址可以省略)
  4. 重定向的路径可以是项目内部的,也可以是项目以外的(eg:百度)
  5. 重定向不能重定向到WEB-INF下的资源
  6. 把数据存到request里面, 重定向不可用
package com.itheima._03_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;

/*
 *  @描述:  使用response进行页面跳转,
 */

@WebServlet("/response02")
public class _02_response extends HttpServlet {

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


        System.out.println("来了一个请求");

/*

        //1. 直接跳转到外面去。
        //a. 设置状态码,302 的意思就是告诉浏览器,还要去另一个地方。
        resp.setStatus(302);

        //Location: http://www.zcmhi.com/archives/94.html
        //resp.setHeader("Location" , "http://www.baidu.com");
        resp.setHeader("Location" , "login.html");
*/

        //-----------------------------较为简单的写法-------------------------------

        resp.sendRedirect("http://www.itheima.com");
    }
}


3.重定向sendRedirect

重定向 response.sendRedirect(“重定向的路径”)

  • 重定向两次请求
  • 重定向的地址栏路径改变
  • 重定向的路径写绝对路径, 带域名/ip地址的(如果路径在同一个项目里面,域名/ip地址可以省略的)
  • 重定向的路径可以写项目内部的, 也可以写项目外部的(eg: 百度)
转发和重定向区别
  1. 重定向可以跳转到外面的资源(网站) , 请求转发跳转不了(只能跳转项目内部资源,因为这是由tomcat来完成)
  2. 请求转发只有一次请求,重定向有两次请求
  3. 请求转发的地址栏不会改变,但是重定向的地址栏会发生改变
  4. 请求转发和重定向都能跳转到servlet
    1. AServlet (request)存值 ----请求转发—到BServlet , 在BServlet里面能取值。
    2. AServlet (request)存值 ----重定向—到BServlet , 在BServlet里面不能取值!!。
  5. 因为WEB-INF 文件夹是受保护的,只能由项目内部跳转,所以请求转发可以跳转到里面的资源,但是重定向不行(因为重定向是从浏览器开始)

在这里插入图片描述

操作响应体

1.操作响应体的API

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rJkK8qp-1619447724882)(img/tu_9.png)]
页面输出只能使用其中的一个流实现,两个流是互斥的

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

/*
 *  @描述:    使用response对象操作响应体
 *
 *          1. 字符流写数据
 *
 *          2. 字节流写数据
 */

@WebServlet("/response03")
public class _03_response extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("来了一个请求");

        //0. 设置响应的内容类型。
        //resp.setContentType("text/html");

        //解决乱码?
        //resp.setCharacterEncoding("UTF-8");

        //00. 既设置了内容的类型,也设置了内容的编码
        resp.setContentType("text/html;charset=utf-8");


        //1. 字符流写数据 如果是字符流,就写上面的resp.setContentType("text/html;charset=utf-8")
        //resp.getWriter().write("<h2><font color='red'>我又又成功啦===success!!!!!</font></h2>");


        //2. 使用字节流写数据 在后面的getBytes里面写上 字符集
        resp.getOutputStream().write("<h2><font color='red'>我想成功!===success!!!!!</font></h2>".getBytes("utf-8"));

    }
}

  1. 为什么会出现乱码?

    • iso8859-1不支持中文
    • 编码和解码不一致
  2. 乱码解决

    • 请求乱码

      • get方式, tomcat>=8.0 不需要解决, 服务器已经解决好了
      • post方式
     request.setCharacterEncoding("utf-8");
     
    
    • 响应乱码
    response.setContentType("text/html;charset=utf-8");
    
    

文件下载

1.需求分析

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

在这里插入图片描述

2.文件下载分析

2.1什么是文件下载

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

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

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

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

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

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

3.思路分析

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

设置两个头和一个流

​ 设置的两个头:

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

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

​ 设置一个流:

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

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

4.代码实现

package com.itheima._05_filedownload;

/*
 *  @描述:    文件下载的servlet
 */

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

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


        //1. 获取要下载的文件名称,通过参数传递进来的
        String fileName = req.getParameter("file");  //a.jpg


        //2. 根据文件找到得到该文件的输入流
//        FileInputStream fis = new FileInputStream();

        InputStream fis = getServletContext().getResourceAsStream("download/"+fileName);

        if(fis == null){
            System.out.println("文件路径错误!!!");

        }

        //设置一下文件的类型,以及告诉浏览器要下载。
        String mimeType = getServletContext().getMimeType(fileName);
        resp.setContentType(mimeType);

        resp.setHeader("Content-Disposition" , "attachment;filename="+fileName);



        //3. 使用字节流的方式写给浏览器
        OutputStream os = resp.getOutputStream();

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

        os.close();
        fis.close();
    }
}


5.细节处理

  • 告诉浏览器设置的响应头里面不支持中文的, 抓包来看:
    在这里插入图片描述

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

中文文件在不同的浏览器中编码方式不同:火狐是Base64编码, 其它浏览器(谷歌)是URL的utf-8编码

if(agent.contains("Firefox")){
			// 火狐浏览器
			filename = base64EncodeFileName(filename);
		}else{
			// IE,其他浏览器
			filename = URLEncoder.encode(filename, "UTF-8");
		}

public static String base64EncodeFileName(String fileName) {
		BASE64Encoder base64Encoder = new BASE64Encoder();
		try {
			return "=?UTF-8?B?"
					+ new String(base64Encoder.encode(fileName
							.getBytes("UTF-8"))) + "?=";
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

综合案例

案例-注册

1. 需求

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

2. 路径

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

3. 代码实现

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9CmSoBwV-1619447724887)(img/tu_12-1568797747077.png)]

  • 不同层次包名的命名

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

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

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

3.2.2准备工作
  • 数据库
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `nickname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `address` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gender` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `hobby` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

  • JavaBean
package com.itheima.bean;

import java.util.Arrays;

/*
 *  @描述:    TODO
 */
public class User02 {

    private String username;
    private String password;
    private String nickname;
    private String address;
    private String email;
    private String gender;
    private String [] hobby;

    public User02() {
    }

    public User02(String username, String password, String nickname, String address, String email, String gender, String[] hobby) {
        this.username = username;
        this.password = password;
        this.nickname = nickname;
        this.address = address;
        this.email = email;
        this.gender = gender;
        this.hobby = hobby;
    }

    ...get方法和set方法...
}


  • 导入jar
  • 工具类和配置文件
  • c3p0-config.xml
<c3p0-config>
    <default-config>

        <!--连接数据库的信息-->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
        <property name="user">root</property>
        <property name="password">root</property>


        <!--连接池的配置-->
        <property name="automaticTestTable">con_test</property>
        <property name="checkoutTimeout">30000</property>
        <property name="idleConnectionTestPeriod">30</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>

        <user-overrides user="test-user">
            <property name="maxPoolSize">10</property>
            <property name="minPoolSize">1</property>
            <property name="maxStatements">0</property>
        </user-overrides>

    </default-config>
</c3p0-config>

  • register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h2>用户注册</h2>

<form method="post" action="register">

    姓名:<input type="text" name="username"/><br/>
    密码:<input type="password" 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" checked="checked" value=""><input type="radio" name="gender" value=""><br/>
    爱好: <input type="checkbox" name="hobby" value="抽烟"/> 抽烟
          <input type="checkbox" name="hobby" value="喝酒"/> 喝酒
          <input type="checkbox" name="hobby" value="烫头"/> 烫头<br/>

    <input type="submit" value="注册"/>
</form>

</body>
</html>

3.2.3 注册案例实现
package com.itheima._06_UserDemo;

import com.itheima.bean.User02;
import com.itheima.db.C3p0Util;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.QueryRunner;

import javax.servlet.ServletConfig;
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.util.Arrays;
import java.util.Map;

/*
 *  @创建时间:  2020/7/28 16:42
 *  @描述:    TODO
 */
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {

    //要想让init方法调用的时机提前 ,还要再web.xml中配置一句话
    // <load-on-startup>1</load-on-startup>
    @Override
    public void init(ServletConfig config) throws ServletException {
       // QueryRunner runner = new QueryRunner(C3p0Util.getDataSource());
    }

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

        try {
            //0. 设置编码
            req.setCharacterEncoding("UTF-8");

            //1. 获取数据
            Map<String, String[]> parameterMap = req.getParameterMap();

            //2. 封装到javabean
            User02 user = new User02();
            BeanUtils.populate(user , parameterMap);

            System.out.println("user=" + user);


            String hobby = Arrays.toString(user.getHobby());
            //3. 往数据库里面添加记录
            QueryRunner runner = new QueryRunner(C3p0Util.getDataSource());
            String sql = "insert into user values (null , ?,?,?,?,?,?,?)";
            int row = runner.update(sql ,
                    user.getUsername(),
                    user.getPassword(),
                    user.getNickname(),
                    user.getAddress(),
                    user.getGender(),
                    hobby.substring(1 ,hobby.length()-1),
                    user.getEmail()
                    );

            if(row > 0){
                System.out.println("注册成功");
            }else{
                System.out.println("注册失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


4. 小结

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

案例-登录

1.需求

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

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

2.思路

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

3.代码实现

3,1准备工作
  • 页面的准备 login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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代码实现
package com.itheima.web;

import com.itheima.bean.User;
import com.itheima.utils.C3P0Utils;
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;
import java.sql.SQLException;

/**
 * @Description:
 * @Author: yp
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        try {
            //0.处理乱码
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            //1.获得用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");

            //2.使用DBUtils根据用户名和密码查询数据库 封装成User对象
            QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
            String sql = "SELECT * FROM user WHERE username = ? AND password  =?";
            User user = queryRunner.query(sql, new BeanHandler<User>(User.class), username, password);
            //3.判断是否登录成功(判断User是否为null)
            if (user != null){
                //3.1 user!= null 响应登录成功
                response.getWriter().print("登录成功!欢迎回来:"+user.getNickname());
            }else{
                //3.2 user== null 响应登录失败
                response.getWriter().print("登录失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().print("登录失败!");
        }
    }

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


4.小结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值