JavaWeb《二》Servlet、Request请求

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 本文是javaweb的第二篇,介绍了Servlet,Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。概述了Request请求与响应,并且主要分析了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的体系结构

image.png

开发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。
image.png

而想发送一个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,首先获取到了请求的方法,然后判断类型:
image.png


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方法。
image.png

当然你也可以重写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>

image.png

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();
    }
}

image.png

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);
    }
}

  • 2、request对象为我们提供了一些方法:前面提到☝

    方法 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解码,编解码不一致因此出现乱码。
image.png

  • 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);
    }
}

解决:
image.png

跳到第一页☝


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

相关文章
|
6月前
|
XML Java 数据格式
Servlet 教程 之 Servlet 客户端 HTTP 请求 3
该教程展示了如何在Servlet中处理客户端HTTP请求,特别是获取HTTP头信息。示例代码创建了一个名为`DisplayHeader`的Servlet,它扩展了`HttpServlet`并重写了`doGet`方法。在`doGet`中,使用`HttpServletRequest`的`getHeaderNames()`遍历所有头部,显示其名称和对应值。Servlet在TomcatTest项目下,通过`web.xml`配置映射到`/TomcatTest/DisplayHeader`路径。
56 14
|
2月前
|
JavaScript Java 容器
servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
本文简要回顾了Servlet过滤器Filter的概念和使用,通过实例演示了如何创建过滤器以过滤请求字符编码,并解释了在web.xml中配置过滤器时使用`/`、`/*`和`/**`的区别。
servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
|
2月前
|
Java 应用服务中间件 Maven
JavaWeb基础5——HTTP,Tomcat&Servlet
JavaWeb技术栈、HTTP、get和post区别、响应状态码、请求响应格数据式、IDEA使用Tomcat、报错解决、Servlet的体系结构、IDEA使用模板创建Servlet
JavaWeb基础5——HTTP,Tomcat&Servlet
|
6月前
|
存储 Java 应用服务中间件
Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解(2)
Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解
67 2
|
6月前
|
Web App开发 XML Java
Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解(1)
Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解
111 2
|
5月前
|
SQL druid Java
javaweb案例实训之基于jsp和servlet的用户管理开发[增删改查及登录注销]
javaweb案例实训之基于jsp和servlet的用户管理开发[增删改查及登录注销]
34 0
|
5月前
|
SQL 数据可视化 数据库
基于jsp+servlet的javaweb实现最基本的用户注册登陆注销功能
基于jsp+servlet的javaweb实现最基本的用户注册登陆注销功能
23 0
|
6月前
|
存储 安全 JavaScript
JavaWeb之Servlet(下)
本文主要介绍了JavaWeb开发中关于请求、响应、会话和Servlet3.0注解的相关知识。首先讲解了请求(Request)的常用方法,以及处理请求乱码问题的几种方式。接着讨论了响应(Response)的方法,,以及设置全局初始化参数。然后介绍了会话(Session)的概念,包括其生命周期、如何设置和获取初始化参数,并对比了全局初始化参数和Servlet3.0的`@WebServlet`注解。文中给出了具体的代码示例和测试结果,帮助读者更好地理解和掌握这些概念。
|
6月前
|
Java 应用服务中间件 程序员
JavaWeb之Servlet(上)
本篇博文介绍了JavaWeb中Servlet的基本概念和应用。Servlet是用于交互式浏览和修改数据、生成动态Web内容的Java程序,通常运行在支持Java的应用服务器上。文章讲解了Servlet的工作模式,包括客户端请求、服务器调用Servlet以及响应返回客户端的过程。此外,还提到了Servlet API,特别是doGet和doPost方法用于处理请求和响应。作者通过创建第一个Servlet的步骤,展示了如何实现Servlet接口并配置web.xml文件。最后,文章简述了Servlet的工作原理和生命周期,强调了Servlet的单例特性以及初始化、服务和销毁的过程。
|
3月前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
33 3