JavaWeb《二》Servlet、Request请求

🍎道阻且长,行则将至。🍓

本文是javaweb的第二篇,介绍了Servlet,Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。概述了Request请求与响应,并且主要分析了Request请求。
上一篇:JavaWeb《一》概念、服务器部署及servlet
下一篇:JavaWeb《三》Request请求转发与Response响应




一、Servlet🍏

Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。上一篇通过seevlet的入门案例,实现了浏览器发出访问请求,我们的idea中可以有所表示。

我们编写一个Servlet就必须要实现Servlet接口,重写接口中的5个方法,但是这样是比较麻烦的,这个过程中我们关注的其实只有service方法。

1.Servlet的体系结构

在这里插入图片描述

开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet可以通过继承HttpServlet来完成。


2.HttpServlet

在上一个基础案例后,继续写一个Servletdemo类继承HttpServlet,重新启动服务器后会自动打包,在浏览器中访问http://localhost:8080/Webapp2_war/demo2

@WebServlet("/demo2")
public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //TODO GET 请求方式处理逻辑
        System.out.println("get...");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //TODO Post 请求方式处理逻辑
        System.out.println("post...");
    }
}

浏览器页面因为本来没内容就是空白,刷新一次在控制台就会get。
在这里插入图片描述
而想发送一个post请求servlet,需要使用form表单了。可以直接在webapp下创建一个index.html页面,在里面加入表单使用post方法,设置action/Webapp2_war/demo2和servlet对应),在浏览器页面访问这个页面提交内容就可以看到post了。

<body>
    <form action="/web-demo/demo4" method="post">
        <input name="username"/><input type="submit"/>
    </form>
</body>

发送GET和POST请求的时候,参数的位置不一致,GET请求参数在请求行中,POST请求参数在请求体中,所以HttpServlet会根据请求方式的不同,调用不同的方法。
我们可以打开HttpServlet看到他实现上层的GenericServletservice方法,然后调用自己的service

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest)req;
            HttpServletResponse response = (HttpServletResponse)res;
            this.service(request, response);
        } else {
            throw new ServletException("non-HTTP request or response");
        }
    }

继续看到service,首先获取到了请求的方法,然后判断类型:
在这里插入图片描述


3.urlPattern配置

Servlet类编写好后,要想被访问到,就需要配置其访问路径:urlPattern
urlPattern可以配置多个,配置规则也有多种

  • 在此前我们一个Servlet只写了一个访问路径,其实它是可以配置多个urlPattern的。
    只需要参数:urlPatterns = {“/demo1”,“/demo2”},就可以输入不同链接来访问servlet了。
    注意这个路径是不能和别人重复了,会报错:
    Caused by: java.lang.IllegalArgumentException: 名为 [ServletDemo1]和 [ServletDemo2] 的servlet不能映射为一个url模式(url-pattern) [/demo1]

  • 精确匹配
    我们此前使用的就是精确匹配,服务路径和配置一致。

  • 目录匹配
    配置为:/user/*
    访问:***/user/aaa***/user/aab或者***/user/abc都可以,就是说配置中的*可以任意替代。
    该方法的优先级低于精确匹配

  • 扩展名匹配
    配置为:*.do
    访问:***/aaa.do或者***/abc.do都可以,配置中的*可以任意替代。

  • 任意匹配
    配置为://*
    访问:任意都可以。但是会导致你的静态资源html都不能访问了。


4.XML配置

在Servlet的配置中我们都使用的是@WebServlet注解方法,这个是Servlet 3.0版本后开始支持注解配置,3.0版本前只支持XML配置文件的配置方法。所以可以了解一下xml配置。
xml配置方法完成Servlet类就不需要加注解了,然后打开WEB_INF里面的web.xml,

    <!--  Servlet 全类名    -->
    <servlet>
        <!-- servlet的名称,名字任意-->
        <servlet-name>demo3</servlet-name>
        <!--servlet的类全名-->
        <servlet-class>Webapp2_war.ServletDemo3</servlet-class>
    </servlet>

    <!--  Servlet 访问路径   -->
    <servlet-mapping>
        <!-- servlet的名称,要和上面的名称一致-->
        <servlet-name>demo3</servlet-name>
        <!-- servlet的访问路径-->
        <url-pattern>/demo3</url-pattern>
    </servlet-mapping>


二、Request🍉

在前面的Servlet或者HttpServlet中,我们都可以看到:ServletRequest req, ServletResponse res参数,这两个参数的作用是什么?

1.request和response

Request是请求对象,Response是响应对象。

  • request:获取请求数据
    • 浏览器会发送HTTP请求到后台服务器;
    • HTTP的请求中会包含很多请求数据:请求行、请求头、请求体;
    • 后台服务器会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中,即request对象,我们可以从request对象中获取请求的相关参数;
    • 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务。
  • response:设置响应数据
    • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据;
    • 把响应数据封装到response对象中;
    • 后台服务器会解析response对象,按照[响应行+响应头+响应体]格式拼接结果;
    • 浏览器最终解析结果,把内容展示在浏览器给用户浏览。

2.request和response对象的使用

我们再写一个Servlet类,在get里面获取请求数据和设置响应数据。

@WebServlet("/demo8")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用request对象 获取请求数据
        String name = request.getParameter("name");
        //使用response对象 设置响应数据
        response.setHeader("content-type","text/html;charset=utf-8");
        response.getWriter().write("<h1>"+name+",欢迎您!</h1>");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Post...");
    }
}

访问的时候在链接后面加上?name=zhangsan,因为这就是直接的get方法。
在这里插入图片描述

当然你也可以重写Post方法,然后在静态页面用post表单传入数据。


3.Request对象

HTTP请求数据总共分为三部分内容,分别是请求行请求头请求体,这三部分内容的数据该如何获取。

  • 获取请求行数据
    请求行包含三块内容,分别是请求方式请求资源路径HTTP协议及版本
    这三部分内容,request对象都提供了对应的API方法来获取:
获取的内容方法
请求方式String getMethod()
虚拟目录(项目访问路径)String getContextPath()
URL(统一资源定位符)StringBuffer getRequestURL()
URI(统一资源标识符)String getRequestURI()
请求参数String getQueryString()

get一下:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // String getMethod():获取请求方式: GET
    String method = req.getMethod();
    System.out.println(method);//GET
    // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
    String contextPath = req.getContextPath();
    System.out.println(contextPath);
    // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
    StringBuffer url = req.getRequestURL();
    System.out.println(url.toString());
    // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
    String uri = req.getRequestURI();
    System.out.println(uri);
    // String getQueryString():获取请求参数(GET方式): username=zhangsan
    String queryString = req.getQueryString();
    System.out.println(queryString);
}
  • 获取请求头数据
    请求头的数据,格式为key: value,根据请求头名称获取对应值的方法为:
String getHeader(String name)
  • 获取请求体数据
    GET请求没有请求体,所以使用请求体需要把请求方式变更为POST。对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:
    • 1、ServletInputStream getInputStream()
      获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法;

    • 2、BufferedReader getReader()
      获取字符输入流,如果前端发送的是纯文本数据,则使用该方法。


4.POST参数获取

参数在请求体中,请求参数获取BufferedReader getReader()

1.准备一个静态页面,添加form表单发送post请求

<form action="/19Webapp2_war/demo8" method="post">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit">
</form>

在这里插入图片描述

2.doPost方法获取数据

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     //获取post 请求体:请求参数
    //1. 获取字符输入流
    BufferedReader br = req.getReader();
    //2. 读取数据
    String line = br.readLine();
    System.out.println(line);
}

点击页面的提交按钮后,就可以在控制台看到前端所发送的请求数据。

3.post具有多个值的参数
如下的hobby就具有两个参数:

<form action="/19Webapp2_war/demo8" method="post">
    <input type="text" name="username"> <br>
    <input type="password" name="password"> <br>
    <input type="checkbox" name="hobby" value="1">swim
    <input type="checkbox" name="hobby" value="2">run<br>
    <input type="submit">
</form>

request对象为我们提供了如下方法,后面还会提到这里:

  • 获取所有参数Map集合
    Map<String,String[]> getParameterMap()
  • 根据名称获取参数值(数组)
    String[] getParameterValues(String name)
  • 根据名称获取参数值(单个值)
    String getParameter(String name)

例如:

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("post~");
    Map<String, String[]> map = req.getParameterMap();
    for (String key : map.keySet()) {
        System.out.print(key + ":");

        String[] values = map.get(key);
        for (String value : values) {
            System.out.print(value + " ");
        }
        System.out.println();
    }
}

在这里插入图片描述

5.GET参数

前面我们进行了POSTt的请求参数获取(BufferedReader getReader()),GET请求和POST请求获取请求参数的方式不一样,GET请求的请求参数在请求行中,在获取请求参数这块该如何实现呢》》》String getQueryString();

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String result = req.getQueryString();
    System.out.println(result);
}

6.POST&GET参数

GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,可以采取一种统一获取请求参数的方式,从而统一doGet和doPost方法内的代码。

  • 1、根据请求方式的不同分别获取请求参数值
    写到一起,然后使用request的getMethod()来获取请求方式。
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求方式
        String method = req.getMethod();
        //获取请求参数
        String params = "";
        if("GET".equals(method)){
            params = req.getQueryString();
        }else if("POST".equals(method)){
            BufferedReader reader = req.getReader();
            params = reader.readLine();
        }
        
        System.out.println(params);      
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

方法M
获取所有参数Map集合Map<String,String[]> getParameterMap()
根据名称获取参数值(数组)String[] getParameterValues(String name)
根据名称获取参数值(单个值)String getParameter(String name)

request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可:

public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //采用request提供的获取请求参数的通用方式来获取请求参数
       //编写其他的业务代码...
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

三、中文乱码🍍

提交中文内容可能在控制台出现乱码

浏览器把中文参数按照UTF-8进行URL编码,Tomcat对获取到的内容进行了ISO-8859-1的URL解码,编解码不一致因此出现乱码。
在这里插入图片描述

在这里插入图片描述

  • POST请求
    设置输入流的编码 : request.setCharacterEncoding("UTF-8");
  • GET/POST通用
    需要先解码,再编码 :new String(username.getBytes("ISO-8859-1"),"UTF-8");
    POST请求参数一般都会比较多,采用这种方式解决乱码起来比较麻烦,所以POST请求建议使用设置编码的方式进行。

Tomcat8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8。

/**
 * 中文乱码问题解决方案
 */
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 解决乱码:POST,getReader()
        //request.setCharacterEncoding("UTF-8");//设置字符输入流的编码

        //2. 获取username
        String username = request.getParameter("username");
        System.out.println("解决乱码前:"+username);

        //3. GET,获取参数的方式:getQueryString
        // 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
       /* //3.1 先对乱码数据进行编码:转为字节数组
        byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
        //3.2 字节数组解码
        username = new String(bytes, StandardCharsets.UTF_8);*/

        username  = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);

        System.out.println("解决乱码后:"+username);

    }

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

解决:
在这里插入图片描述
在这里插入图片描述

跳到第一页☝


☕物有本末,事有终始,知所先后。🍭

🍎☝☝☝☝☝我的CSDN☝☝☝☝☝☝🍓

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super algorithm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值