1,request对象和resqonse对象的原理

  • request对象是来获取请求消息,response对象是来设置响应消息的

request

1,request对象继承体系结构:
ServletRequest(接口)----(继承自)----HttpServletRequest(接口)----(继承自)----org.apache.catalina.connector.requestFacade(类tomcat)

2,request功能:获取请求对象消息

  • 获取请求行数据:
  • GET /day14/demo1?name=zhangsan HTTP/1.1
  • 方法:
  • 1,获取请求方式 :GET
  • String getMethod()
  • 2,获取虚拟目录:/day14_request_war_exploded
  • String getContextPath()
  • 3, 获取Servlet路径:/RequestDemo1
  • String getServletPath()
  • 4, 获取get方式请求参数:name=zhangsan
  • String getQueryString()
  • 5,获取请求URI:/day14_request_war_exploded/RequestDemo1
  • String getRequestURI():/day14_request_war_exploded/RequestDemo1
  • StringBuffer getRequestURL() :http://localhost:8080/day14_request_war_exploded/RequestDemo1
  • URL:统一资源定位符
  • URI:统一资源标识符
  • 6,获取协议以及版本号:HTTP/1.1
  • String getProtocol()
  • 7,获取客户机的IP地址:
  • String getRemoteAddr()

示例:

package cn.jsp.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;
/**
 * 演示Request对象获取请求行数据
 */
@WebServlet("/RequestDemo1")
public class RequestDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求方式
        String method = request.getMethod();
        System.out.println(method);
        //获取虚拟目录
        String contextPath = request.getContextPath();
        System.out.println(contextPath);
        //获取Servlet路径
        String servletPath = request.getServletPath();
        System.out.println(servletPath);
        //获取get方式请求参数
        String queryString = request.getQueryString();
        System.out.println(queryString);
        //获取请求URI
        String requestURI = request.getRequestURI();
        System.out.println(requestURI);
        StringBuffer requestURL = request.getRequestURL();
        System.out.println(requestURL);
        //获取协议以及版本
        String protocol = request.getProtocol();
        System.out.println(protocol);
        //获取客户机IP
        String remoteAddr = request.getRemoteAddr();
        System.out.println(remoteAddr);
    }
}

运行结果:

java解析response内容的方法 java获取response_System

  • 获取请求头数据:
  • 方法:
  • 1,String getHeader(String name):通过请求头的名称获取请求头的值
package cn.jsp.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;
import java.util.Enumeration;

@WebServlet("/RequestDemo2")
public class RequestDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //演示获取请求头数据
        //1,获取所有请求头名称
        Enumeration<String> headerNames = request.getHeaderNames();
        //遍历
        while (headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            //根据名称获取请求头的值
            String value = request.getHeader(name);
            System.out.println(name + "---" + value);
        }
    }
}

运行结果:

host---localhost:8080
connection---keep-alive
cache-control---max-age=0
upgrade-insecure-requests---1
user-agent---Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3947.100 Safari/537.36
accept---text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding---gzip, deflate, br
accept-language---zh-CN,zh;q=0.9
cookie---JSESSIONID=AFA50683AA3D9544C967B201C7F2580F; Idea-712eb87f=92c060fc-0b9a-4df6-b2c3-cb9900a2b912
  • 2,Enumeration<String> getHeaderNames():获取所有的请求头名称
  • 获取请求体数据:
  • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
  • 步骤:
  • 1,获取流对象:
  • BufferedReader getReader():获取字符输入流,只能操作字符数据
  • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求消息体---请求参数
        //1,获取字符流
        BufferedReader br = request.getReader();
        //2,读取数据
        String line = null;
        while((line = br.readLine()) != null){
            System.out.println(line);
        }
    }
  • 其他功能:
  • 1,获取请求参数通用方式:get和post请求都可以使用下列方法获取
  • 1,String getParameter(String name):根据参数名称获取参数值
  • 2,String[ ] getParameterValues(String name):根据参数名称获取参数值的数组
  • 3,Enumeration<String> getParameterNames():获取所有请求参数的参数名称
  • 4,Map<String,String[]> getParameterMap():获取所有参数的map集合
package cn.jsp.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;
import java.util.Map;
import java.util.Set;

@WebServlet("/requestDemo6")
public class RequestDemo6 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //post 获取请求参数
        //设置流的编码
        request.setCharacterEncoding("utf-8")
        //根据参数名称获取参数值
        String username = request.getParameter("username");
        //根据参数名称获取参数值的数组
        String[] hobbies = request.getParameterValues("hobby");
        /*
        for (String hobby : hobbies){
            System.out.println(hobby);
        }
        */
        //获取所有请求参数的参数名称
        /*
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();
            System.out.println(name);
            String value = request.getParameter(name);
            System.out.println(value);
            System.out.println("--------------------------------");
        }
        */
        //获取所有参数的map集合
        Map<String, String[]> parameterMap = request.getParameterMap();
        //遍历
        Set<String> keyset = parameterMap.keySet();
        for (String name : keyset){
            //获取键获取值
            String[] values = parameterMap.get(name);
            System.out.println(name);
            for (String value :values){
                System.out.println(value);
            }
            System.out.println("-------------------------");
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*//get 获取请求参数
        //根据参数名称获取参数值
        String username = request.getParameter("username");
        System.out.println("get");
        System.out.println(username);*/
        this.doPost(request,response);
    }
}
  • 中文乱码问题:
  • get方式:tomcat8已经将get方式乱码问题解决
  • post方式:会乱码
  • 解决:在获取参数前,设置request的编码
  • request.setCharacterEncoding("utf-8");
  • 2,请求转发:一种在服务器内部的资源跳转的方式
  • 步骤:
  • 1,通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
  • 2,使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse response)
  • 下面是主要实现代码:
//转发到demo8资源
        /*
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("requestDemo8");
        requestDispatcher.forward(request,response);
        */
        request.getRequestDispatcher("/requestDemo8").forward(request,response);
  • 特点:
  • 1,浏览器地址栏路径不发生变化
  • 2,只能转发到当前服务器内部资源中
  • 3,转发是一次请求
  • 3,共享数据
  • 域对象:一个有作用范围的对象,可以在范围内共享数据
  • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
  • 方法:
  • 1,void setAttribute(String name,Object obj):存储数据
//存储数据到request域中
        request.setAttribute("msg","hello");
  • 2,Object getAttribute(String name):通过键获取值
//获取数据
        Object msg = request.getAttribute("msg");
        System.out.println(msg);
  • 3,void removeAttribute(String name):通过键移除键值对
  • 4,获取ServletContext:
  • ServletContext getServletContext()ServletContext servletContext = request.getServletContext();

BeanUtils工具类

简化数据封装:commons-beanutils-1.8.0.jar

用于封装JavaBean的

  • JavaBean:标准Java类
  • 1,要求:
  • 1,类必须被public修饰
  • 2,必须提供空参的构造器
  • 3,成员变量必须使用private修饰
  • 4,提供公共的setter和getter方法
  • 2,功能:封装数据

示例:

/*
        //获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //封装user对象
        User loginUser = new User();
        loginUser.setUsername(username);
        loginUser.setPassword(password);
      */

        //获取所有请求参数
        Map<String, String[]> map = request.getParameterMap();
        //创建User对象
        User loginUser = new User();

        //使用BeanUtils封装
        try {
            BeanUtils.populate(loginUser,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

Response

响应消息:服务器端发送给客户端的数据

  • 数据格式:
  • 1,响应行
  • 1,组成:协议/版本 响应状态码 状态码描述
  • 2,响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
  • 3,响应状态码分类:
  • 1,1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多状态码
  • 2,2xx:成功。代表:200
  • 3,3xx:重定向。代表:302(重定向),304(访问缓存)
  • 4,4xx:客户端错误。代表:404(请求路径没有对应的资源);405(请求方式没有对应的doXxx方法)
  • 5,5xx:服务端错误。代表:500(服务器端出现异常)
  • 2,响应头
  • 1,格式:头名称:值
  • 2,常见的响应头:
  • 1,Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
  • 2,Content-disposition:服务器告诉客户端以什么格式打开响应体数据
  • in-line:默认值,在当前页面内打开
  • attachment;filename-xxx:以附件形式打开响应体。文件下载
  • 3,响应空行
  • 4,响应体:传输的数据

Response对象

功能:设置响应消息

  • 1,设置响应行
  • 1,格式:HTTP/1.1 200 OK
  • 2,设置状态码:setStatus(int sc)
  • 2,设置响应头:setHeader(String name,String value)
  • 3,设置响应体
  • 使用步骤:
  • 1,获取输出流
  • 字符输出流:PrintWriter getWriter()
  • 字节输出流:ServletOutputStream getOutputStream()
  • 2,使用输出流,将数据输出到客户端浏览器

案列

1,完成重定向

  • 重定向:资源跳转的方式
//访问/responseDemo1会自动跳转到/responseDemo2
        /*//1,设置状态码为302
        response.setStatus(302);
        //2,设置响应头location
        response.setHeader("location","/day15/responseDemo2");
        */
        //简单的重定向方法
        response.sendRedirect("/day15/responseDemo2");
  • 重定向的特点:redirect(和转发(forward)的特点对比)
  • 1,地址栏发生变化
  • 2,重定向可以访问其他站点(服务器)的资源
  • 3,重定向是两次请求,不能使用reques对象来共享数据。

2,服务器输出字符数据到浏览器
步骤:

  • 1,获取字符输出流
  • 2,输出数据

注意乱码问题:解决办法如下

//设置编码
        //resp.setCharacterEncoding("utf-8");
        //告诉浏览器,服务器发送消息体数据的编码,建议浏览器使用该编码
        //resp.setHeader("content-type","text/html;charset=utf-8");
        //简单形式设置编码,在获取流之前
        resp.setContentType("text/html;charset=utf-8");
        //获取字符输出流
        PrintWriter pw = resp.getWriter();//获取的流默认编码是ISO-8859-1
        //输出数据
        //pw.write("<h1>hello response</h1>");
        pw.write("你好,response");

3,服务器输出字节数据到浏览器
步骤:

  • 1,获取字节输出流
  • 2,输出数据
//简单形式设置编码
        resp.setContentType("text/html;charset=utf-8");
        //获取字节输出流
        ServletOutputStream sos = resp.getOutputStream();
        //输出数据
        sos.write("你好,hello".getBytes("utf-8"));

ServletContext 对象

1,概念:代表整个web应用,可以和整个程序的容器(服务器)来通信
2,获取

  • 1,通过request对象获取
  • request.getServletContext();
  • 2,通过HttpServlet获取
  • this.getServletContext(); 3,功能:
  • 1,获取MIME类型:
  • MIME类型:在互联网通信过程中定义的一种文件数据类型
  • 格式: 大类型/小类型 text/html image/jpeg
  • 获取:String getMimeType(String file)
  • 2,域对象:共享数据
  • 1,setAttribute(String name,Object value)
  • 2,getAttribute(String name)
  • 3,removeAttribute(String name)
  • ServletContext对象范围:所有用户所有请求的数据
  • 3,获取文件的真实(服务器)路径
  • 1,方法:String getRealPath(String path)
//通过HttpServlet获取
        ServletContext context = this.getServletContext();
        //获取文件的服务器路径
        String realPath = context.getRealPath("/b.txt");
        File file = new File(realPath);
        //System.out.println(realPath);

        String c = context.getRealPath("/WEB-INF/c.txt");
        System.out.println(c);

案例:文件下载
文件下载需求:

  • 1, 页面显示超链接
  • 2,点击超链接后弹出下载提示框
  • 3,完成图片文件下载

步骤:

  • 1,定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
  • 2,定义Servlet
  • 1,获取文件名称
  • 2,使用字节输入流加载文件进内存
  • 3,指定response的响应头:content-disposition:attachment;filename=xxx
  • 4,将数据写出到response输出流
package cn.jsp.web.download;
import cn.jsp.web.utils.DownLoadUtils;
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;

@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数,文件名称
        String filename = request.getParameter("filename");
        //使用字节输入流加载文件进内存
        //找到文件服务器路径
        ServletContext servletContext = this.getServletContext();
        String realPath = servletContext.getRealPath("/img/" + filename);
        //用字节流关联
        FileInputStream fis = new FileInputStream(realPath);
        //设置response的响应头
        //设置响应头类型:content-type
        String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
        response.setHeader("content-type",mimeType);
        //设置响应头打开方式:content-disposition
        //解决中文文件名问题
        //获取user-agent请求头
        String agent = request.getHeader("user-agent");
        //使用工具类方法编码文件名即可
        filename = DownLoadUtils.getFileName(agent, filename);
        response.setHeader("content-disposition","attachment;filename="+filename);

        //将输入流的数据写出到输出流中
        ServletOutputStream sos = response.getOutputStream();
        byte[] buff = new byte[1024 * 8];
        int len = 0;
        while((len=fis.read(buff))!=-1){
            sos.write(buff,0,len);
        }
        fis.close();
    }

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