Servlet(中)
标签(空格分隔): JavaWeb
HTTP协议
什么是HTTP协议
WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议。
HTTP是 hypertext transfer protocol(超文本传输协议)的简写,它是 TCP/IP 协议集中的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程以及数据本身的格式。
HTTP的会话方式
四个步骤:
- 建立连接
- 发出请求信息
- 回送响应信息
- 关闭连接
浏览器与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方式传递参数:
- 在浏览器地址栏中输入某个URL地址或单击网页上的一个超链接时,浏览器发出的HTTP请求消息的请求方式为GET。
- 如果网页中的表单元素的method属性被设置为了“GET”,浏览器提交这个FORM表单时生成的HTTP请求消息的请求方式也为GET。
- 使用GET请求方式给WEB服务器传递参数的格式:
http://localhost:8080/counter.jsp?name=root&password=123
- 使用GET方式传送的数据量一般限制在1KB以下。
使用 POST 方式传递参数:
- POST 请求方式主要用于向 WEB 服务器端程序提交 FORM 表单中的数据: form 表单的 method 置为 POST。
- 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中定义。非常重要,后面再说。
小练习
- 在 web.xml 文件中设置两个 WEB 应用的初始化参数,user, password.
- 定义一个 login.html,里边定义两个请求字段: user, password。 发送请求到 loginServlet
- 创建一个 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 {
}
}