day03——servlet请求和响应

Servlet请求

Servlet请求对应的是ServletRequest对象,它有一个子类HttpServletRequet基于Http协议的规则对请求数据进行了封装。我们可以使用HttpServletRequet对象的方法来获取请求数据,来完成功能的开发。

1.获取路径的方法

public String getContextPath() //发布项目时所写的虚拟目录  /servlet
    获取虚拟目录路径 
public String getServletPath()//访问资源的路径	     /ServletDemo1
    获取Servlet的映射路径
public String getRemoteAddr()
    获取访问者的ip地址
public String getQueryString()
    获取请求的消息数据
public String getRequestURI()//虚拟目录和访问资源的路径一起获取到 	/servlet/ServletDemo1
    获取统一资源标识符
public String getRequestURL()//完整路径   http://localhost:8080/servlet/ServletDemo1
    获取统一资源定位符
    ps:URI比URL范围更大
@WebServlet("/servletRequestDemo1")
public class ServletRequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取虚拟目录
        String contextPath = req.getContextPath();
        System.out.println("虚拟目录:"+contextPath); 

        //获取Servlet映射路径
        String servletPath = req.getServletPath();
        System.out.println("servlet访问路径:"+servletPath);

        //获取访问者ip地址: 
        String remoteAddr = req.getRemoteAddr();
        System.out.println("访问者ip:"+remoteAddr);

        //获取统一资源标识符
        String requestURI = req.getRequestURI();
        System.out.println("资源标识符:"+requestURI);

        //获取统一资源定位符
        StringBuffer requestURL = req.getRequestURL();
        System.out.println("统一资源定位符:"+requestURL);
    }

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

2.获取请求头信息

请求头是浏览器告诉服务器的一些请求配置信息,以键值对的形式存在。

public String getHeader(String name)
    获取一个请求头的值
public Enumeration<String> getHeaders(String name)
    获取一个请求头的多个值
public Enumeration<String> getHeadNames()
    获取所有请求头名称
@WebServlet("/servletRequestDemo2")
public class ServletRequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取一个请求头
        String connection = req.getHeader("connection");
        System.out.println(connection);
        System.out.println("----------------");

        //获取一个请求头的多个值
        Enumeration<String> values = req.getHeaders("accept-encoding");
        while (values.hasMoreElements()) {
            String value = values.nextElement();
            System.out.println(value);
        }

        System.out.println("------------");

        //获取所有的请求头名称
        Enumeration<String> headerNames = req.getHeaderNames();
        //遍历请求头名称,根据名称获取值
        while (headerNames.hasMoreElements()) {
            String headName = headerNames.nextElement();
            String headValue = req.getHeader(headName);
            System.out.println(headName+"="+headValue);
        }
    }

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

3.获取请求参数信息

public String getParameter(String name)
    根据参数名获取一个参数值
public String[] getParameterValues(String name)
    根据参数名获取多个参数值
public Enumeration<String> getParameterNames()
    获取所有的参数名称
public Map<String,String[]> getParameterMap()
    获取所有的参数名和参数值,并封装为Map集合

创建一个regist.html页面(参考源代码),然后使用Servlet获取参数信息

@WebServlet("/servletRequestDemo3")
public class ServletRequestDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //根据参数名获取参数指
        String username = req.getParameter("username");
        System.out.println("姓名:"+username);

        //根据参数名获取多个值
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("爱好:"+ Arrays.toString(hobbies));
        System.out.println("---------");
        //获取所有的参数名称
        Enumeration<String> parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameterName = parameterNames.nextElement();
            String[] values = req.getParameterValues(parameterName);
            System.out.println(parameterName+":"+Arrays.toString(values));
        }
        System.out.println("----------");

        //获取所有的参数名和参数指,存入一个Map集合
        Map<String, String[]> parameterMap = req.getParameterMap();
        Set<String> keys = parameterMap.keySet();
        for (String key : keys) {
            String[] values = parameterMap.get(key);
            System.out.println(key+"="+Arrays.toString(values));
        }
    }

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

4.请求数据封装对象

需要用到beanutils工具类,把jar包复制到web/WEB-INF/libs目录下

@WebServlet("/servletRequestDemo5")
public class ServletRequestDemo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取所有的参数名和参数指,存入一个Map集合
        Map<String, String[]> parameterMap = req.getParameterMap();
        Student stu=new Student();
        try {
            BeanUtils.populate(stu,parameterMap);
            System.out.println(stu);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

通过流对象获取数据

public BufferedReader getReader()
    ----获取字符输入流
    ps:借住io流获取数据,表单的请求方式必须是post
public ServletInPutStream getInPutStream()
    ----获取字节输入流

5.请求数据乱码解决

//设置请求字符编码
req.setCharacterEncoding("utf-8");

6.请求转发-请求域

  • 请求域(也叫request域):可以在一次请求范围内进行共享数据(一般用于请求转发的多个资源中共享数据)

  • 当客户端请求一个Servlet1时,Servlet1可以将请求转发给Servlet2,同时可以转发过程中共享数据。多次转发形成的一条请求链,叫做请求域。可以在请求域访问内共享数据。

  • 请求转发:客户端的一次请求到达后,发现需要借住其他Servlet来实现功能

  • 特点:

    • 浏览器地址栏不变
    • 域对象中的数据不丢失
    • 负责转发的Servlet转发前后的响应正文会丢失
    • 由转发的目的地来响应客户端
  • 方法

    - public RequestDispatcher getRequestDispacher(String name) ---获取请求调度对象
    String name---转发的Servlet的映射路径
    - public void forward(ServletRequest req,ServletReponse resp) ---实现转发
    
  • 在Servlet7中设置共享数据

@WebServlet("/servletRequestDemo7")
public class ServletRequestDemo7 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求编码
        req.setCharacterEncoding("utf-8");

        //设置请求参数
        req.setAttribute("user","李四");
        req.getRequestDispatcher("/servletRequestDemo8").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 在Servlet8中获取共享数据
@WebServlet("/servletRequestDemo8")
public class ServletRequestDemo8 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求编码
        req.setCharacterEncoding("utf-8");

        //获取请求共享数据
        Object user = req.getAttribute("user");
        System.out.println(user);
    }

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

Servlet响应

浏览器访问服务器后,服务器给客户端响应的数据会封装为ServletResponse对象,它有一个子类叫HttpServletResponse对象,用于封装按照Http协议封装的响应数据。

  • 响应:就是回馈结果,在B/S架构中,就是服务器端给客户端浏览器反馈结果
  • 响应对象:就是在项目中用于发送响应的对象

1.响应状态码

状态码状态
100只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求
200请求成功
302重定向,所请求的页面已经临时转移到一个新的 URL
304访问缓存,所请求的页面已经临时转移到一个新的 URL
404客户端错误,请求路径服务器没有对应的资源
405客户端错误,请求方式找不到对应的方法
500服务端错误,可能服务器内部有异常

2.响应数据乱码解决

//设置响应编码,解决中文乱码问题
public void setContentType("text/html;charset=utg-8")
resp.setContentType("text/html;charset=utf-8");
  • 使用字符流响应数据

    • public PrintWriter getWriter()

      获取响应字符流输出对象

@WebServlet("/servletResponseDemo1")
public class ServletResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置响应编码
        resp.setContentType("text/html;charset=utf-8");
        //输出响应数据
        resp.getWriter().println("<h1>你好,这是一个响应消息</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 使用字节流响应数据

    • public ServletOutputStream getOutputStream()

      获取响应字节输出流对象

@WebServlet("/servletResponseDemo2")
public class ServletResponseDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置响应编码
        resp.setContentType("text/html;charset=utf-8");
        //输出响应数据
        ServletOutputStream outputStream = resp.getOutputStream();
        outputStream.write("你好世界".getBytes("utf-8"));
    }

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

3.响应图片

在web/img目录下放一张a.jpeg图片,把图片中所有的字节响应给客户端。

  • 创建字节输入流对象,关联读取的图片路径
    • 注意:发布项目后图片路径会变,要获取项目发布后的绝对路径
  • 通过响应对象获取字节输出流对象
  • 循环读取和写出图片
@WebServlet("/servletResponseDemo3")
public class ServletResponseDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取输出流对象
        ServletOutputStream out = resp.getOutputStream();
        //获取文件的绝对路径
        String imgPath = getServletContext().getRealPath("img/a.jpeg");
        //获取输入流对象
        FileInputStream fis = new FileInputStream(imgPath);
        byte[] bs=new byte[1024];
        int len;
        while ((len=fis.read(bs))!=-1){
            out.write(bs,0,len);
        }
        fis.close();
    }

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

4.设置缓存[了解]

  • 缓存:对于不经常变化的数据,我们可以合理设置缓存时间,以避免浏览器频繁请求服务器,以此来提高效率.

  • public void setDateHeader(String name,long time)

    设置消息头添加缓存

    String name 直接写成Expires

    • 注意:像Chrome和Firefox等高级的浏览器无法进行显示

      @WebServlet("/servletDemo4")
      public class ServletDemo4 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String str = "这是一条劲爆的新闻";
              //设置缓存时间1小时
              resp.setDateHeader("Expires",System.currentTimeMillis()+1000*1*60*60);
              //设置编码格式
              resp.setContentType("text/html;charset=utf-8");
              //输出消息
              resp.getWriter().write(str);
              //添加一条信息,查看缓存是否设置
              System.out.println("我执行了...");
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req, resp);
          }
      }
      

5.设置定时刷新

  • 定时刷新:过了指定时间后,页面自动进行跳转
  • pubIic void setHeader(String name,String value)

​ 设置消息头定时刷新(消息头的名称,指定时间和跳转目的地)

@WebServlet("/servletResponseDemo5")
public class ServletResponseDemo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Refresh","3;url=/day03_Servlet/login.html");
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().println("你好世界 三秒钟跳转到登录页面");
    }

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

6.重定向

  • 重定向:客户端的一次请求到达后,发现需要借助其他Servlet来实现功能
  • 特点:浏览器地址栏会发生改变,两次请求,请求域对象中不能共享数据,可以重定向到其他服务器
  • public void setRedirect(String name) ------设置重定向

重定向和请求转发不太一样,请求转发是只有一个请求,而重定向有两次请求。所以重定向不能通过请求域共享数据,只有在同一个请求链中才能通过请求域中心数据。

@WebServlet("/servletResponseDemo6")
public class ServletResponseDemo6 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        //重定向到servletResponseDemo5
        //resp.sendRedirect(req.getContextPath()+"/servletResponseDemo5");

        //也可以使用下面两个方法,完成重定向;302表示重定向的状态码
        resp.setStatus(302);
        resp.setHeader("location",req.getContextPath()+"/servletResponseDemo5");
    }

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

7.文件下载

  • 创建字节输入流,关联读取的文件

  • 设置响应消息头支持的类型

    • public void setHeader(“Content-Type”,applicatin/octet-stream)

      /*

      ​ Content-Type:消息头名称 支持的类型

      ​ application/octet-stream:消息头参数 应用的类型为字节流

      */

  • 设置响应消息头以下载方式打开资源

    • public void setHeader(“Content-Disposition”,“attachement;filename=a.jpg”)

      /*

      ​ Content-Disposition:消息头名称 处理形式

      ​ attachment;filename=a.jpg:消息头参数 附件形式进行处理 指定下载文件的名称

      */

  • 通过响应对象获取字节输出流对象

  • 循环读写

  • 释放资源

写一个html页面,点击图片开始下载

<a href="/day03_Servlet/servletResponseDemo7">点击下载图片</a> 

写以Servlet处理下载的请求,给客户端响应一张图片

@WebServlet("/servletResponseDemo7")
public class ServletResponseDemo7 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //准备要下载的图片
        File file=new File("img/a.jpeg");

        //设置响应头,告诉浏览器以附件形式接受
        resp.setHeader("content-disposition","attachment;filename="+file.getName());

        //获取输出流对象
        ServletOutputStream out = resp.getOutputStream();
        //获取文件的绝对路径
        String imgPath = getServletContext().getRealPath(file.getPath());
        //获取输入流对象
        FileInputStream fis = new FileInputStream(imgPath);
        byte[] bs=new byte[1024];
        int len;
        while ((len=fis.read(bs))!=-1){
            out.write(bs,0,len);
        }
        fis.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值