JavaWeb实验课---4.2请求与响应---2022.10

4.2 请求与响应

4.2.1 响应 - HttpServletResponse

步骤:

  • 目标:能响应中文到浏览器,能设计重定向
  • 响应状态行
  1. 创建一个项目ch0406,创建一个CodeServlet.java文件,父类为HttpServlet。HttpServlet继承自GenericServlet,所以HttpServlet中重写了GenericServlet中的service方法:将req、res强制转换,再去调用HttpServlet类中的另一个service方法。
  2. 继承自HttpServlet,主要重写doGet和doPost方法。doPost方法中调用doGet方法。响应标头默认是200,通过setStatus方法可以修改响应标头(结果1)。也可以通过SendError方法修改
  3. 解决中文乱码问题
  • 响应header
  1. 乱码产生:在doGet方法的getWriter方法中写入“中文”两个字,启动程序后页面出现乱码。
  2. 在setContentType中既要告诉服务器用utf-8编码,同时这个信息也会发送给浏览器,浏览器就知道了可以用utf-8方式解码。
  • 重定向
  1. 创建一个TimeServlet.java文件,用来显示时间。
  2. 通过Date()获得当前时间,通过SimpleDateFormat把时间变成字符串形式,通过format()格式化日期。然后把字符串形式的dateStr添加到resp.getWriter方法下,输出在浏览器页面上
  3. 创建一个RedirectServlet.java,希望访问redirect时可以重定向过去:通过sendRedirect方法。sendRedirect的参数可以为time,也可以为req.getContextPath() + “/time”。

代码:

  1. 响应行状态:
@WebServlet("/code1")
public class CodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//(弃用方法)    resp.setStatus(201);
        resp.setCharacterEncoding("utf-8");
        resp.sendError(404,"lost.....");
        resp.getWriter().append("Served at: ").append(req.getContextPath());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
  1. 响应header:
@WebServlet("/chn")
public class ChineseServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("school","cqrk");
//        resp.setLocale(Locale.CHINA);
        resp.setContentType("text/html;charset=utf-8");
//这个方法不保险        resp.setCharacterEncoding("utf-8");
        resp.getWriter().append("中文002 Served at: ").append(req.getContextPath());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 重定向
@WebServlet("/time")
public class TimeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyy/MM/dd HH:mm:ss");
        String dateStr = sdf.format(now);

        resp.getWriter().append("Served at: ").append(dateStr);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect(req.getContextPath() + "/time");
        //resp.sendRedirect("time");
    }

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

实验结果:

  1. 响应行状态
    结果1:响应标头用setStatus方法修改为201(该方法已被弃用)
    在这里插入图片描述
    结果2:响应标头用sendError方法修改为404(此时会出现中文乱码)
    在这里插入图片描述

结果3:在sendError方法前加上setCharacterEncoding方法,参数为utf-8
在这里插入图片描述
2. 响应header
结果1: 产生乱码
在这里插入图片描述
结果2: 使用setContentType解决乱码
在这里插入图片描述
3. 重定向
结果1: time页面显示时间
在这里插入图片描述
结果2: redirect页面重定向
在这里插入图片描述

4.2.2 响应图片

步骤:

  1. 用Java GUI生成验证码图片,使用Java imageio把图片写到输出流。
  2. 在webapp文件夹下创建一个login.html,里面写了一个image标签,当点击这张图片时,执行script里面的代码

代码:

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

        //1. content-type 返回图片类型
 /**ServletContext功能之一:获取MIME类型:
 * MIME类型:在互联网通信过程中定义的一种文件数据类型
 * 格式: 大类型/小类型   text/html        image/jpeg
 * 获取:String getMimeType(String file) 
 * */
        String mimeType = getServletContext().getMimeType(".jpg");
        System.out.println("mimetype" + mimeType);
        resp.setContentType(mimeType);

        //不缓存
        //resp.setHeader("Cache-Control","no-store");

        //2. 画图大小
        int w = 100;
        int h = 50;

        //3. 生成BufferedImage对象
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = bufferedImage.getGraphics();

        //4. 填充矩形
        graphics.setColor(Color.LIGHT_GRAY);//颜色
        graphics.fillRect(0, 0, w, h);//矩形从左上角(0,0)到(x,y)

        //5. 画外框
        graphics.setColor(new Color(34, 34, 250));//先设置一个颜色
        graphics.drawRect(0, 0, w-1, h-1);//画一个矩形框

        //6. 在这张图片上写4个字母
        graphics.setFont(new Font("",Font.BOLD,20));
        Random random = new Random();
        for (int i = 0; i < 4; i++){    //随机生成4个字符,画在图片里
            char x = (char) ('A' + random.nextInt(25));
            graphics.drawString(""+x, 5+i*20, 30);
        }

        //7. 画随机线条
        for(int i = 0; i < 10; i++){
            int x1 = random.nextInt(100);
            int x2 = random.nextInt(100);
            int y1 = random.nextInt(50);
            int y2 = random.nextInt(50);
            graphics.drawLine(x1, y1, x2, y2);
        }

        //8. 把图片写出到输出流
        ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--当点击这张图片时,就会执行下面的script代码-->
    img: <img id="code" alt="" src="check" onclick="freash()">
  <script>
    function freash(){
      let check = document.getElementById("code");
      check.src="check?"+new Date().getTime();
      console.log("freash2....")//控制台上输出freash....
    }
  </script>
</body>
</html>

实验结果:

在这里插入图片描述
在这里插入图片描述

4.2.3 请求行、请求头获取

步骤:

  1. 创建一个RequestLineServlet.java文件,继承自HttpServlet
  2. 在doGet方法中,设置ContentType为中文,通过resp.getWriter方法输出请求行的相关信息
  3. 创建一个RequestHeaderServlet.java文件,继承自HttpServlet
  4. 请求消息过来后,除了请求行,还有很多的请求头,这些请求头怎么去取数据?
  5. 设置响应的ContentType,拿到getWriter,通过调用req的getHeaderNames方法拿到所有头字段。再写个循环去遍历取出headerName,通过req.getHeader把headerName传进去。就能取出header的值

代码:

@WebServlet("/reqTest")
public class RequestLineServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        //获取请求行的相关信息
        out.println("getMethod : " + req.getMethod() + "<br>");
        out.println("getRequestURI : " + req.getRequestURI() + "<br>");
        out.println("getQueryString : " + req.getQueryString() + "<br>");
        out.println("getProtocol : " + req.getProtocol() + "<br>");
        out.println("getContextPath : " + req.getContextPath() + "<br>");
        out.println("getPathInfo : " + req.getPathInfo() + "<br>");
        out.println("getPathTranslated : " + req.getPathTranslated() + "<br>");
        out.println("getServletPath : " + req.getServletPath() + "<br>");
        out.println("getRemoteAddr : " + req.getRemoteAddr() + "<br>");
        out.println("getRemoteHost : " + req.getRemoteHost() + "<br>");
        out.println("getRemotePort : " + req.getRemotePort() + "<br>");
        out.println("getLocalAddr : " + req.getLocalAddr() + "<br>");
        out.println("getLocalName : " + req.getLocalName() + "<br>");
        out.println("getLocalPort : " + req.getLocalPort() + "<br>");
        out.println("getServerName : " + req.getServerName() + "<br>");
        out.println("getServerPort : " + req.getServerPort() + "<br>");
        out.println("getScheme : " + req.getScheme() + "<br>");
        out.println("getRequestURL : " + req.getRequestURL() + "<br>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/reqHeader")
public class RequestHeaderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        //获取请求消息中所有头字段
        Enumeration<String> headerNames = req.getHeaderNames();
        //使用循环遍历所有请求头,并通过getWriter()方法获取一个指定名称的头字段
        while (headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            out.println(headerName + ":" + req.getHeader(headerName) + "<br>");
        }
    }

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

实验结果:

在这里插入图片描述
在这里插入图片描述

4.2.4 请求参数的获取

步骤:

  • 表单提交数据
  1. 表单form.html:form标签的action特性:当用户提交时,把数据提交给指定的url。method用来指定Http请求的方式:get。
  2. 下面是用户名、密码标签,爱好复选框,提交按钮submit,当用户点击提交按钮,表单就会把数据提交给URL,这个URL对应的RequestParamsServlet下面的@WebServlet。
  • 服务端程序获取参数
  1. 当用户点击提交按钮后,数据就会提交给action。如果method是get请求,tomcat就会调用doGet方法;如果method为post,tomcat就会去调用doPost方法。doPost方法中会转去调用doGet方法
  2. 通过req.getParameter方法获得用户名、密码对应的值,在控制台输出。复选框用户有可能会选多个,所以通过req.getParameterValues()得到二维数组hobbies,然后把爱好输出在控制台。
  • 解决参数乱码问题
  1. 如果提交的表单中用户名是中文,控制端输出为乱码
  2. 加一句req.setCharacterEncoding(“utf-8”);//这里填utf-8是因为在form.html中的content中为utf-8,即浏览器发送的编码是content中的utf-8,解码的时候指定也要是utf-8
  • 问题:请求参数的获取:在实际开发中,经常需要获取用户提交的表单数据。例如,用户名、密码、电子邮件,那么处理程序怎么得到用户填写的内容呢?这些信息可能出现在url中(get请求,把数据通过get方法传过来),在请求体当中(post请求)
  • 解决办法:在HttpServlet接口中,定义了一系列获取请求参数的方法。
  1. String getParameter(String name)获取某个指定名称的参数值。
  2. String[] getParameterValues(String name)如果要获得HTTP请求消息中的同一个参数名对应的所有参数值
  3. Enumeration getParameterNames()该方法返回一个包含请求消息中所有参数名的Enumeration对象,在此基础上,可以对请求消息中的所有参数进行遍历处理。
  4. Map getParameterMap()用于将请求消息中的所有参数名和值装入进一个Map对象中返回

代码:

@WebServlet("/RequestParamServlet")
public class RequestParamsServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String name = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("用户名:" + name);
        System.out.println("密  码:" + password);
        //获取参数名为hobby的值
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("爱好:");
        if(hobbies != null){
            for (String hobby1 : hobbies) {
                System.out.println(hobby1 + ",");
            }
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

实验结果:

  • 表单提交数据(get和post两种方法)
    在这里插入图片描述
    在这里插入图片描述
    改成post方法:
    在这里插入图片描述
  • 通过HttpServletRequest获取请求参数
    在这里插入图片描述

4.2.5 请求转发forward

步骤:

  1. 请求转发:
    当浏览器发送请求,访问Servlet1,在Web服务器端的Servlet容器中servlet1通过forward()方法把这个请求交给其他Web资源进行处理,其他Web资源再把响应结果给浏览器。
  2. 请求包含:
    当浏览器发送请求,访问Servlet1,在Web服务器端的Servlet容器中通过RequestDispatcer调用include()方法把Servlet1和其他web资源一起响应浏览器,把结果给浏览器。
  • forward基本使用
  1. 通过req.getRequestDispatcher,参数填URL:/SecondServlet,得到一个RequestDispatcher类型的变量,定义为dispatcher
  2. 在FirstServlet通过req.setAttribute方法把数据放到request域对象里面,在SecondServlet通过req.getAttribute方法把数据取出来、展示出来。(一个Servlet负责处理数据,另一个Servlet负责把数据展示出来,就可以把代码分开)
  3. 调用resp的getWriter方法将数据写到缓存器,tomcat没有发送,调用RequestdDispatcher的forward()方法

代码:

get方法请求转发:

@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher dispatcher = req.getRequestDispatcher("/SecondServlet");
        req.setAttribute("msg","sqrk lalal");

        resp.getWriter().append("first 01 Served at: ").append(req.getContextPath());
        dispatcher.forward(req,resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/SecondServlet")
public class SecondServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object msg = req.getAttribute("msg");
        resp.getWriter().append("second Served at: " + msg).append(req.getContextPath());
    }

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

post方法请求转发:

@WebServlet("/FirstServlet2")
public class FirstServlet2 extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher dispatcher = req.getRequestDispatcher("/SecondServlet2");
        req.setAttribute("msg","cqrk1234");

        resp.getWriter().append("first 0001 Served at: ").append(req.getContextPath());
        dispatcher.include(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/SecondServlet2")
public class SecondServlet2 extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("school","cqrk");
        Object msg = req.getAttribute("msg");
        resp.getWriter().append("second 0002 Served at: " + msg).append(req.getContextPath());
    }

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

实验结果:

在这里插入图片描述

4.2.6 请求包含

步骤:

forward方法:会把请求转发过去,当前的Servlet不会对请求进行响应。
include方法:两个servlet产生的内容都会出现在浏览器端

  1. 在FirstServlet中将forward方法改为include方法
  2. 在SecondServlet中加一句setHeader方法,添加一个school\cqrk

代码:

@WebServlet("/FirstServlet2")
public class FirstServlet2 extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher dispatcher = req.getRequestDispatcher("/SecondServlet2");
        req.setAttribute("msg","cqrk1234");

        resp.getWriter().append("first 0001 Served at: ").append(req.getContextPath());
        dispatcher.include(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/SecondServlet2")
public class SecondServlet2 extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("school","cqrk");
        Object msg = req.getAttribute("msg");
        resp.getWriter().append("second 0002 Served at: " + msg).append(req.getContextPath());
    }

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

实验结果:

FirstServlet和SecondServlet的内容都显示出来了
**加粗样式**
响应标头中并没有setHeader中的内容
在这里插入图片描述

4.2.7 作业:简单的验证登录

步骤:

目的:

  1. 静态页面:login.html登录表单(至少包含用户名、密码)
    home.html模拟登录后可见的数据管理页面
  2. LoginServlet对login.html提交的用户名-密码验证,通过验证(abc, 123)则显示home.html,如果不成功,则让用户继续登录
  3. 扩展:登录后显示登录用户名
    步骤:
  4. login.html表单中action代表数据要提交到哪里去,method使用post请求方式,两个文本框账号、密码,一个提交按钮
  5. home.jsp表单中,模拟用户登录成功后的页面
  6. 访问home静态页面时,因为home在WEB-INF下,不能被浏览器直接访问。Home页面需要用户登录成功后,才能访问到
  7. loginServlet中通过req.getParameter得到用户账号和密码,判断是否跟abc、123相同
  8. 如果验证的话,通过req.setAttribute()将用户输入的username保存到域对象里,home.jsp取到传过来的域对象,把用户名显示到页面上。通过req.getRequestDispatcher调用forward方法跳转去home页面
  9. 如果验证不成功,就重定向到login

代码:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String pwd = req.getParameter("pwd");

        if("abc".equals(username) && "123".equals(pwd)){
            req.setAttribute("name",username);
            req.getRequestDispatcher("/WEB-INF/home.jsp").forward(req,resp);
        }else {
            resp.sendRedirect("/ch0407_war_exploded/login.html");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--post和get都可以-->
      <form action="login" method="post">
        <input type="text" name="username" placeholder="账号" />
        <input type="text" name="pwd" placeholder="密码"/>
        <input type="submit" value="登陆">
      </form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>管理首页</h1>
    <h4>登陆用户:${name}</h4>
    添加成绩<br/>
    修改成绩<br/>
    ....<br/>
</body>
</html>

实验结果:

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值