03 Servlet(中)

Servlet(中)

标签(空格分隔): JavaWeb


HTTP协议

什么是HTTP协议

WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议。

HTTP是 hypertext transfer protocol(超文本传输协议)的简写,它是 TCP/IP 协议集中的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程以及数据本身的格式。

HTTP的会话方式

四个步骤:

  1. 建立连接
  2. 发出请求信息
  3. 回送响应信息
  4. 关闭连接

浏览器与WEB服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一个页面的访问,浏览器与WEB服务器都要建立一次单独的连接。

浏览器到WEB服务器之间的所有通讯都是完全独立分开的请求和响应对。

HTTP请求消息

客户端连上服务器后,向服务器请求某个web资源,称之为客户端向服务器发送了一个HTTP请求。

请求消息的结构:一个请求行、若干消息头、以及实体内容,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。

GET /books/java.html HTTP/1.1   <!--请求行-->
Accept: */*                     <!--以下是多个消息头-->
Accept-Language: en-us
Connection: Keep-Alive
Host: localhost
Referer: http://localhost/links.asp
User-Agent: Mozilla/4.0
Accept-Encoding: gzip, deflate
                                <!--一个空行-->
  • 请求行:用于描述客户端的请求方式、请求的资源名称,以及使用的HTTP协议版本号。
  • 消息头:用于描述客户端请求那一台主机,以及客户端的一些环境信息等。

请求行中的GET称之为请求方式,请求方式有:POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT,常用的有: GET、 POST

用户如果没有设置,默认情况下浏览器向服务器发送的都是get请求,例如在浏览器直接输地址访问,点超链接访问等都是get,用户如想把请求方式改为post,可通过更改表单的提交方式实现。

HTTP响应消息

响应消息的实体内容就是网页文件的内容,也就是在浏览器中使用查看源文件的方式所看到的内容。

响应消息的结构:一个状态行、若干消息头、以及实体内容,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。

HTTP/1.1 200 OK                         <!--状态行-->
Server: Microsoft-IIS/5.0               <!--以下是多个消息头-->
Date: Thu, 13 Jul 2000 05:46:53 GMT
Content-Length: 2291
Content-Type: text/html
Cache-control: private
                                        <!--一个空行-->
<html>
    <body></body>                       <!--实体内容-->
</html>
  • 状态行: 用于描述服务器对请求的处理结果
  • 消息头:用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会他回送的数据。
  • 实体内容:代表服务器向客户端回送的数据

GET & POST

GET和POST是两种常用的请求方式。

使用GET方式传递参数:

  1. 在浏览器地址栏中输入某个URL地址或单击网页上的一个超链接时,浏览器发出的HTTP请求消息的请求方式为GET。
  2. 如果网页中的表单元素的method属性被设置为了“GET”,浏览器提交这个FORM表单时生成的HTTP请求消息的请求方式也为GET。
  3. 使用GET请求方式给WEB服务器传递参数的格式:
    http://localhost:8080/counter.jsp?name=root&password=123
  4. 使用GET方式传送的数据量一般限制在1KB以下。

使用 POST 方式传递参数:

  1. POST 请求方式主要用于向 WEB 服务器端程序提交 FORM 表单中的数据: form 表单的 method 置为 POST。
  2. POST 方式将各个表单字段元素及其数据作为 HTTP 消息的实体内容发送给 WEB 服务器,传送的数据量要比使用GET方式传送的数据量大得多。

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <!--要注意表单是form不是from...-->
    <form action = "loginServlet" method = "post">
        user:<input type="text" name="user"/>
        password:<input type="password" name="password"/>
        <input type="submit" value="Submit"/>
    </form>
</body>
</html>

注意: action = “loginServlet” 表示当提交表单时向loginServlet发送表单数据。

ServletRequest

在Servlet中获取请求信息

在上面的html代码中,我们已经可以通过from表单,将数据以post的方法提交到loginServlet中,这是一种请求。

那么我们也可以在Servlet中获取请求信息。

Servlet 的 service() 方法用于应答请求: 因为每次请求都会调用 service() 方法:

public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
}

ServletRequest: 封装了请求信息。可以从中获取到任何的请求信息。
ServletResponse: 封装了响应信息, 如果想给用户什么响应,具体可以使用该接口的方法实现。

这两个接口的实现类都是服务器给予实现的,并在服务器调用 service 方法时传入。

form表单提交到servlet的方法

首先:创建一个 用于登录的jsp页面有一个form表单用于提交用户名和密码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <!--要注意表单是form不是from...-->
    <form action = "loginServlet" method = "post">
        user:<input type="text" name="user"/>
        password:<input type="password" name="password"/>
        <input type="submit" value="Submit"/>
    </form>
</body>
</html>

然后我们要创建一个loginServlet类,要在service()方法中写代码,一会再写代码:

package test;
import javax.servlet.*;
import java.io.IOException;

public class loginServlet implements Servlet{
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init...");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

最后我们要做的就是在web.xml中注册和映射该Servlet文件:

<!--配置和映射Servlet-->
    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>test.loginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>loginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>

其中要注意的是:

  • <servlet-name>loginServlet</servlet-name> 这个注册名是没有硬性要求的。
  • <url-pattern>/loginServlet</url-pattern>这里的url是我们要按照from表单中的action属性写的url来填写,即/loginServlet

获取请求参数

ServletRequest: 封装了请求信息。 可以从中获取到任何的请求信息。我们下面看一下它的方法,并且作为例子卸载service()中。

  • String getParameter(String name):
    根据form表单中请求参数的名字,返回参数值。若请求参数有多个值(例如 checkbox), 该方法只能获取到第一个提交的值。
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service...");
        String user = servletRequest.getParameter("user");
        String password = servletRequest.getParameter("password");
        System.out.println("user:" + user + "  password:" + password);
    }

结果为:在html界面输入了值,点击Submit后,loginServlet通过表单中的name属性,获取到了参数:

service...
user:root  password:1234
  • String[] getParameterValues(String name):
    根据请求参数的名字,返回请求参数对应的字符串数组。
    有时候我们从表单中想要通过一次请求获取一组数据,比如checkbox属性:
interesting:
        <input type="checkbox" name="interesting" value="reading"/>Reading
        <input type="checkbox" name="interesting" value="shopping"/>Shopping
        <input type="checkbox" name="interesting" value="singing"/>Singing
        <input type="submit" value="Submit"/>

那么如果我们继续使用String getParameter(String name),在请求参数有多个值的情况下只能获取到第一个提交的值。

因此我们要使用String[] getParameterValues(String name)方法:

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        String[] interestings = servletRequest.getParameterValues("interesting");
        for (String interest : interestings) {
            System.out.println("checkbox: " + interest);
        }
    }

输出的结果为:

checkbox: reading
checkbox: shopping
checkbox: singing
  • numeration getParameterNames():
    返回参数名对应的 Enumeration 对象,类似于 ServletConfig(或ServletContext)的getInitParameterNames() 方法
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        Enumeration<String> names = servletRequest.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String val = servletRequest.getParameter(name);

            System.out.println("--" + name + ":" + val);
        }
    }

输出结果为:

--user:root
--password:1234
--interesting:reading
  • Map getParameterMap():
    返回请求参数的键值对: key: 参数名,value: 参数值,String 数组类型。
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

       Map<String,String[]> map = servletRequest.getParameterMap();
        for (Map.Entry<String,String[]> entry : map.entrySet()) {
            System.out.println("**" + entry.getKey() + ":" + Arrays.asList(entry.getValue()));
        }
    }

输出结果为:

**user:[root]
**password:[1234]
**interesting:[reading, shopping, singing]

获取请求的URI

首先我们来看一下什么是URI:

URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。

而URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。

也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL则是具体的资源标识的方式。URL是一种URI。在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的,schema必须被指定。

HttpServletRequest:是 ServletRequest 的子接口,针对于HTTP请求所定义。里面包含了大量 获取HTTP请求相关的方法。

    HttpServletRequest httpServletRequest = (HttpServletRequest) request;

    String requestURI = httpServletRequest.getRequestURI();
    System.out.println(requestURI); 

输出为:

/first/loginServlet

获取请求方式:

    String method = httpServletRequest.getMethod();
    System.out.println(method); 

输出为:

GET

若是一个 GET 请求, 获取请求参数对应的那个字符串, 即 ? 后的那个字符串。

    String queryString = httpServletRequest.getQueryString();
    System.out.println(queryString); 

输出为:

user=root&password=1234&interesting=game&interesting=party&interesting=shopping

如果是POST请求,则返回null

获取请求的 Serlvet 的映射路径

   String servletPath = httpServletRequest.getServletPath();
   System.out.println(servletPath);  

输出为:

/loginServlet

ServletResponse

封装了响应信息,如果想给用户什么响应,具体可以使用该接口的方法实现。

其中的很多方法都不太常用。

getWriter()

返回PrintWrite对象。调用该对象的 print() 方法,将把 print() 中的参数直接打印到客户的浏览器上。

PrintWriter out = response.getWriter();
out.println("hello...");

设置响应的内容类型

response.setContentType("application/msword");

返回一个word文件

请求的重定向

void sendRedirect(String location)

此方法为HttpServletResponse中定义。非常重要,后面再说。

小练习

  1. 在 web.xml 文件中设置两个 WEB 应用的初始化参数,user, password.
  2. 定义一个 login.html,里边定义两个请求字段: user, password。 发送请求到 loginServlet
  3. 创建一个 LoginServlet, 在其中获取请求的 user, password。比对其和 web.xml 文件中定义的请求参数是否一致。

web.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!--配置和映射Servlet-->
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>test.loginServlet</servlet-class>

        <init-param>
            <param-name>user</param-name>
            <param-value>root</param-value>
        </init-param>

        <init-param>
            <param-name>password</param-name>
            <param-value>1234</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

html文件中:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <form action="login" method="post">
        username:<input type="text" name="username"/>
        password:<input type="password" name="password"/>
        <input type="submit" value="Submit"/>
    </form>

</body>
</html>

在service()方法中获取ServletConfig对象可能有问题,因此直接创建servlet类

//忽略导入的包

@WebServlet(name = "loginServlet")
public class loginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("service...");
        ServletConfig servletConfig = this.getServletConfig();
        String configUser = servletConfig.getInitParameter("user");
        String configPassword = servletConfig.getInitParameter("password");
        System.out.println("配置中的用户名" + configUser);
        System.out.println("配置中的密码" + configPassword);


        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("输入的用户名" + configUser);
        System.out.println("输入的密码" + configPassword);

        if (username.equals(configUser)) {
            PrintWriter out1 = response.getWriter();
            out1.println("user name is right!");
            if (password.equals(configPassword)) {
                PrintWriter out2 = response.getWriter();
                out2.println("login successful!" + username);
            } else {
                PrintWriter out3 = response.getWriter();
                out3.println("password is wrong!" + username);
            }
        } else {
            PrintWriter out4 = response.getWriter();
            out4.println("No username!");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值