servlet
a)什么是servlet
1.servlet是javaee规范之一,规范就是接口,
2.servlet是javaee三大组件之一,三大组件分别是servlet程序,filter过滤器,listener监听器
3.servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并响应数据给客户端,
b)手动实现servlet程序
1.编写一个类去实现servlet接口
2.实现servlet方法,处理请求,并响应数据
3.到web.xml中去配置servlet程序的访问地址
Servlet 程序的示例代码:
package com.atguigu.servlet;
import javax.servlet.*;
import java.io.IOException;
public class helloServlet implements Servlet {
//servlet方法专门用来处理请求和响应的
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("hello servlet 被访问了");
}
@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中的配置
<?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_4_0.xsd"
version="4.0">
<!--servlet标签给tomcat配置tomcart程序-->
<servlet>
<!--servlet-name 标签servlet程序起一个别名(一般是类名)-->
<servlet-name>helloServlet</servlet-name>
<!--servlet-class是servlet程序的全类名-->
<servlet-class>com.atguigu.servlet.helloServlet</servlet-class>
</servlet>
<!--servlet-mapping标签给servlet程序配置访问地址-->
<servlet-mapping>
<!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个servlet程序使用-->
<servlet-name>helloServlet</servlet-name>
<!--url-pattern标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为http://ip:port/工程路径
/hello 表示地址为: http://ip:port/工程路径/hello-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
常见的错误:
常见的错误一:
url-pattern中配置的路径没有以斜杠打头
Caused by: java.lang.IllegalArgumentException: Invalid hello in servlet mapping
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3195)
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3182)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1384)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1192)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:782)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:307)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
… 43 more
常见错误2:
servlet-name配置的值不存在
Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name helloServlet1
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3191)
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3182)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1384)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1192)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:782)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:307)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
… 43 more
常见错误三:
servlet-class配置的全类名配置错误
javax.servlet.ServletException: Error instantiating servlet class com.atguigu.srvlet.helloServlet
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
org.apache.coyote.AbstractProtocol
A
b
s
t
r
a
c
t
C
o
n
n
e
c
t
i
o
n
H
a
n
d
l
e
r
.
p
r
o
c
e
s
s
(
A
b
s
t
r
a
c
t
P
r
o
t
o
c
o
l
.
j
a
v
a
:
684
)
o
r
g
.
a
p
a
c
h
e
.
t
o
m
c
a
t
.
u
t
i
l
.
n
e
t
.
A
p
r
E
n
d
p
o
i
n
t
AbstractConnectionHandler.process(AbstractProtocol.java:684) org.apache.tomcat.util.net.AprEndpoint
AbstractConnectionHandler.process(AbstractProtocol.java:684)org.apache.tomcat.util.net.AprEndpointSocketProcessor.doRun(AprEndpoint.java:2527)
org.apache.tomcat.util.net.AprEndpoint
S
o
c
k
e
t
P
r
o
c
e
s
s
o
r
.
r
u
n
(
A
p
r
E
n
d
p
o
i
n
t
.
j
a
v
a
:
2516
)
j
a
v
a
.
b
a
s
e
/
j
a
v
a
.
u
t
i
l
.
c
o
n
c
u
r
r
e
n
t
.
T
h
r
e
a
d
P
o
o
l
E
x
e
c
u
t
o
r
.
r
u
n
W
o
r
k
e
r
(
T
h
r
e
a
d
P
o
o
l
E
x
e
c
u
t
o
r
.
j
a
v
a
:
1130
)
j
a
v
a
.
b
a
s
e
/
j
a
v
a
.
u
t
i
l
.
c
o
n
c
u
r
r
e
n
t
.
T
h
r
e
a
d
P
o
o
l
E
x
e
c
u
t
o
r
SocketProcessor.run(AprEndpoint.java:2516) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) java.base/java.util.concurrent.ThreadPoolExecutor
SocketProcessor.run(AprEndpoint.java:2516)java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)java.base/java.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:630)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:832)
c)url地址到servlet程序的访问
客户端(浏览器)
http://localhost:8080/test_war_exploded/hello
http://表示http协议
localhost是服务器ip
:8080是服务器的端口号
/test_war_exploded 是工程路径
/hello 是资源路径
通过ip地址定位到服务器
通过端口号定位tomcat
通过工程路径知道要访问哪个工程
类
public class helloServlet{
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("hello servlet 被访问了");
}
}
web.xml配置文件
服务器 硬件 电脑 ip地址(唯一)
8080端口 tomcat服务器
里面有:
/test_war_exploded工程
/abc 工程
/book 工程……
<servlet>
<!--servlet-name 标签servlet程序起一个别名(一般是类名)-->
<servlet-name>helloServlet</servlet-name>
<!--servlet-class是servlet程序的全类名-->
<servlet-class>com.atguigu.servlet.helloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个servlet程序使用-->
<servlet-name>helloServlet</servlet-name>
<!--url-pattern标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为http://ip:port/工程路径
/hello 表示地址为: http://ip:port/工程路径/hello-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
d)servlet的生命周期
1.执行servlet构造器的方法
2.执行init初始化方法
第一第二步是在创建servlet程序会使用
3.执行service方法
第三步 每次访问都会被调用
4.执行destroy销毁方法
第四步在web停止的时候被调用
e)get和post的分发处理
package com.atguigu.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class helloServlet implements Servlet {
public helloServlet() {
System.out.println("1 构造器方法");
}
//servlet方法专门用来处理请求和响应的
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init初始化方法");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3 service()方法");
//类型转换 (因为它有getMethod() 方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
if("GET".equals(method)){
doGet();
}else if("POST".equals(method)){
doPost();
}
}
public void doGet(){
System.out.println("get请求");
}
public void doPost(){
System.out.println("post请求");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4 destroy()销毁方法 ");
}
}
f)通过继承httpservlet实现servlet程序
一般在实际项目开发中,都是使用继承httpServlet类的方式去实现servlet程序
1.编写一个类去继承hpptservlet类
2.根据业务需要重写doGet或doPost方法
3.到web.xml中配置Servlet程序的访问地址
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class helloServlet2 extends HttpServlet {
//doGet()在get请求的时候调用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("helloservlet2的doGet方法");
}
//doPost()在post请求时调用
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("helloservlet2的doPost方法");
}
}
g)使用idea创建servlet程序
菜单→new→servlet程序
配置servlet的信息
h)servlet的继承体系
1.继承树
interface servlet :只是负责定义servlet程序的访问规范
↑ 实现接口
class GenericServlet :实现了servlet接口,做了很多空实现,并持有一个servletconfig类的引用,并对servletconfig的使用做一些方法
↑ 继承
class HttpServlet : HttpServlet抽象实现了service()方法,并且实现了请求的分类处理
↑ 继承 String method = req.getmethod()
自定义的servlet程序 GET POST
doGet() doPost() 负责抛异常,说不支持get和post请求
我们只需要根据自己的任务需要去重写doGet和doPost方法即可
2.servletConfig类
servletConfig类 从类名上来看,就知道是servlet程序的配置信息类
a)servletconfig类的三大作用
1.可以获取servlet程序的别名servlet-name的值
2.获取初始化参数init-param
3.获取servletContext的对象
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init初始化方法");
//1.可以获取servlet程序的别名servlet-name的值
System.out.println("hellosServle的别名是"+servletConfig.getServletName());
//2.获取初始化参数init-param
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("url"));
//3.获取servletContext的对象
System.out.println(servletConfig.getServletContext());
}
在别的地方使用servletconfig对象
package com.atguigu.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class helloServlet2 extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("重写了init初始化方法,做了一些工作");
}
//doGet()在get请求的时候调用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("helloservlet2的doGet方法");
//也可以使用
ServletConfig servletConfig = getServletConfig();
System.out.println(servletConfig);
System.out.println(servletConfig.getInitParameter("username"));
}
//doPost()在post请求时调用
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("helloservlet2的doPost方法");
}
}
<?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_4_0.xsd"
version="4.0">
<!--servlet标签给tomcat配置tomcart程序-->
<servlet>
<!--servlet-name 标签servlet程序起一个别名(一般是类名)-->
<servlet-name>helloServlet</servlet-name>
<!--servlet-class是servlet程序的全类名-->
<servlet-class>com.atguigu.servlet.helloServlet</servlet-class>
<!--init param是初始化参数-->
<init-param>
<!--是参数名-->
<param-name>username</param-name>
<!--是参数值-->
<param-value>root</param-value>
</init-param>
</servlet>
<!--servlet-mapping标签给servlet程序配置访问地址-->
<servlet-mapping>
<!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个servlet程序使用-->
<servlet-name>helloServlet</servlet-name>
<!--url-pattern标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为http://ip:port/工程路径
/hello 表示地址为: http://ip:port/工程路径/hello-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>helloServlet2</servlet-name>
<servlet-class>com.atguigu.servlet.helloServlet2</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>root2</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>helloServlet3</servlet-name>
<servlet-class>com.atguigu.servlet.helloServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet3</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
</web-app>
注意 重写会覆盖掉父类方法 所以要使用super关键字调用父类方法
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config); 注意这里
System.out.println("重写了init初始化方法,做了一些工作");
}
3.servletContext类
a)什么是servletContext
1.servletcontext是一个接口,他表示servlet上下文对象
2.一个web工程,只有一个servletContext对象实例
3.servletcontext是一个域对象,
4.4.servletcontext是在web工程中部署的时候启动创建,在web工程停止的时候销毁它
什么是域对象?
域对象,是和map一样可以存储数据的对象,叫域对象
这里的域指的存储数据的操作范围,这里的操作范围为web项目**
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
map | put() | get() | remove() |
servletContext | putAttribute() | getAttribute() | removeAttribute() |
b)ServletContext类的四个作用
1.获取web.xml中配置的上下文参数context-param
2.获取当前的工程路径,格式:/工程路径
3.获取工程部署后在服务器在磁盘上的绝对路径
4.像map一样存储数据
功能测试:
package com.atguigu.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class ContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.获取web.xml中配置的上下文参数context-param
ServletContext servletContext = getServletConfig().getServletContext();
System.out.println("context-param参数username的值是"+servletContext.getInitParameter("username"));
System.out.println("context-param参数password的值是"+servletContext.getInitParameter("password"));
// 2.获取当前的工程路径,格式:/工程路径
System.out.println("当前工程路径为:"+getServletConfig().getServletContext().getContextPath());
// 3.获取工程部署后在服务器在磁盘上的绝对路径
// / 斜杠被服务器解析为http://ip:port/工程名/
// 映射到idea代码的web目录
System.out.println("工程部署的路径是"+getServletConfig().getServletContext().getRealPath("/"));
System.out.println("工程下的css目录"+getServletConfig().getServletContext().getRealPath("/css"));
System.out.println("工程下的image下的1.jpg的路径是"+getServletConfig().getServletContext().getRealPath("/image/1.jpg"));
}
// 以下地址是idea整合tomcat之后,tomcat被拷贝的一些副本内容
//Using CATALINA_BASE: "C:\Users\26523\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\009e2895-4f0a-4989-aadc-b4300d96c7c5"
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
输出结果:
context-param参数username的值是context
context-param参数password的值是root
当前工程路径为:/test_war_exploded
工程部署的路径是C:\Users\26523\IdeaProjects\test\target\test-1.0-SNAPSHOT
工程下的css目录C:\Users\26523\IdeaProjects\test\target\test-1.0-SNAPSHOT\css
工程下的image下的1.jpg的路径是C:\Users\26523\IdeaProjects\test\target\test-1.0-SNAPSHOT\image\1.jpg
4.http协议
a)什么是http协议
什么是协议?
协议指的是双方,多方,相互约定好,大家都需要遵守的规则,叫做协议
所谓http协议就是指,客户端和服务器通信时,发送的数据,需要遵守的规则,叫hhtp协议
http协议中的数据又叫报文
b)请求的http协议格式
客户端给服务器发送数据叫做请求
服务器给服务器回传数据叫响应
请求又分为get请求和post请求两种
i.GET请求
1.请求行
(1)请求的方式 GET
(2)请求的资源路径[+?+请求参数]
(3)请求的协议的版本号 HTTP/1.1
2.请求头
key:value 组成 不同的储值对,表示不同的含义
请求行:
1.请求的方式: GET
2.请求的资源路径 /test_war_explored/a.html
3.请求到协议的版本号 HTTP/1.1
Accept:告诉服务器可以接收到的数据类型
Accept—language:告诉服务器客户端可以接收的语言类型
zh_CN 中文中国
en_US 英文美国
User-Agent: 就是浏览器的信息
Accept-Encoding: 告诉服务器,客户端可以接收的数据编码(压缩)格式
Host:表示请求的服务器ip和端口号
Connection:告诉服务器请求连接如何处理
keep-alive 告诉服务器回传数据不要马上关闭,保持一小段时间的连接
closed 马上关闭
ii post请求
1.请求行
1.请求的方式: POST
2.请求的资源路径 /test_war_explored/a.html
3.请求到协议的版本号 HTTP/1.1
2.请求头
1)key:value 不同的请求头有不同的含义
空行
3.请求体 ======= 就是发送给服务器的数据
以下是post请求的http协议内容
请求行
POST /test_war_exploded/hello HTTP/1.1
1.请求的方式 post
2.请求的资源路径 /test_war_exploded/hello
3.请求的协议和版本号 HTTP/1.1
请求头:
Host: localhost:8080
Connection: keep-alive
Content-Length: 26
Cache-Control: max-age=0
sec-ch-ua: “Google Chrome”;v=“93”, " Not;A Brand";v=“99”, “Chromium”;v=“93”
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: “Windows”
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/test_war_exploded/a.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=3586F254239F3856FE08F9A589AB0F0A; Idea-c372728b=41df1464-46ec-4bba-b8c1-d85a2c936a1f
空行
accept:表示可以接收到的数据类型
accept-language 表示客户端可以接受的语言类型
referer: 表示请求发起时,浏览器地址栏中的地址(从哪来)
user-agent:表示浏览器的信息
content-type表示发送的数据的类型
application/x-www-form-urlencoded 表示提交的数据格式类型是:name=value&&name=value 然后对其进行url编码
url编码是把非英文内容转换为:%xx%xx的形式
multipart/form-data 表示以多段的形式提交给服务器(以流的形式提交,用于上传)
content-length:表示发送的数据的长度
cache-control:表示如何控制缓存 no—cache不缓存
请求体:发送给服务器的数据
username=root&action=login
iii 常用请求头的说明
accept:表示客户端可以接受的数据类型
accept-language:表示客户端可以接受的语言类型
user-agent:表示客户端浏览器的信息
host: 表示请求时的服务器ip和端口号
iv:哪些是get请求,哪些是post请求
get请求有哪些
1.form标签 method = get
2.a标签
3.link标签引入css
4.script标签引入js文件
5.img标签引入图片
6.iframe引入html页面
7.在浏览器地址栏中输入地址后敲回车
post请求有哪些
1.form标签 method = post
c)响应的http协议格式
1.响应行
(1)响应的协议和版本号 http:/1.1
(2) 响应状态码 200
(3) 响应状态描述符 ok
2.响应头
(1)key:value 不同的响应头有不同的含义
空行
3.响应体 ---- 就是回传给客户端的数据
以下的内容就是响应的http协议实例:
响应行:
1.响应的协议 http
2.响应状态码 200
3.响应状态描述符 ok
响应头:
server:表示服务器的信息
Content-type:表示响应体的数据类型
content-length:响应体的数据长度
date:请求响应的时间(格林时间)
响应行
HTTP/1.1 200 OK
响应头
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Wed, 08 Sep 2021 10:33:59 GMT
空行
响应体
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/test_war_exploded/hello2" method="get">
<input type="submit" value="提交"/>
</form>
</body>
</html>
d)常用的响应码说明
200 表示请求成功
302 表示请求重定向
404 表示请求服务器已经收到了,但是你要的数据不存在 (请求地址错误)
500 表示服务器已经收到请求,但是服务器内部错误(代码错误)
e)MIME类型说明
mime是http协议中数据类型
mime的英文全称是"multipurpose Internet Mail Extensions"多功能internet邮件扩充服务,mime类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应
常见的mme类型
文本 | mime类型 |
---|---|
超文本标记语言文本 | .html,.htm text/html |
普通文本 | .txt text/plain |
RTF文本 | .rtf application/rtf |
gif图形 | .gif image/gif |
JPEG图形 | .jpeg,.jpg image/jpeg |
au声音文件 | .au audio/basic |
MIDI声音文件 | .midi,.mid audio/midi audio/x-midi |
RealAudio声音文件 | .ram,.ra audio/x-pn-realaudio |
mpeg文件 | .mpeg/.mpg video/x-msvideo |
AVI文件 | .avi video/x-msvideo |
GZIP文件 | .gz application/x-gzip |
TAR文件 | .tar application/x-tar |
如何用谷歌浏览器查看HTTP协议内容
如何用火狐浏览器查看http协议内容
5.httpServletRequest类
a)httpServletRequest类的作用
每次只要有请求进入tomcat服务器就会把请求过来的http协议解析好封装到request对象中
然后传递到service方法里(doget和dopost)中给我们使用,我们可以通过httpServletRequest对象,获取到所有的信息,
b)httpservletrequest类的常用方法
i. getRequestURI() 获取请求的资源路径
ii. getRequestURL() 获取请求的统一的资源定位符(绝对路径)
iii. getRemoteHost() 获取客户端的ip地址
iv. getHeader() 获取请求头
vii. getMethod() 获取请求的方式GET或POST
viii. setAttribute(key, value); 设置域数据
ix. getAttribute(key); 获取域数据
x. getRequestDispatcher() 获取请求转发对象
package com.atguigu.Servlet;
import com.example.demo.HelloServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestApiServlet extends HelloServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// i. getRequestURI() 获取请求的资源路径 uri:/demo_war_exploded/hello
System.out.println("uri:"+request.getRequestURI());
//ii. getRequestURL() 获取请求的统一的资源定位符(绝对路径) url:http://localhost:8080/demo_war_exploded/hello
System.out.println("url:"+request.getRequestURL());
//iii. getRemoteHost() 获取客户端的ip地址 客户端ip地址:127.0.0.1
/*
* 在idea中获取localhost的ip地址为127.0.0.1
* 在idea中获取127.0.0.1的ip地址为127.0.0.1
* 在idea中获取真实的ip的ip地址为真实的ip地址
* */
System.out.println("客户端ip地址:"+request.getRemoteHost());
//iv. getHeader() 获取请求头 请求头:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.38
System.out.println("请求头:"+ request.getHeader("User-Agent"));
// vii. getMethod() 获取请求的方式GET或POST
System.out.println("请求的方式:"+request.getMethod());}
c)如何获取请求参数
v. getParameter() 获取请求的参数
vi. getParameterValues() 获取请求的参数(多个值的时候使用)
Servlet程序代码:
package com.atguigu.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//v. getParameter() 获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//vi. getParameterValues() 获取请求的参数(多个值的时候使用)
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("爱好:"+ Arrays.asList(hobby));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求体的字符集为utf-8,从而解决post请求的中文乱码问题
//也要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
System.out.println("--------doPost---------");
//获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("爱好:"+ Arrays.asList(hobby));
}
}
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/demo_war_exploded/hello2" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="cpp"/>c++
<input type="checkbox" name="hobby" value="java"/>java
<input type="checkbox" name="hobby" value="javascript"/>javascript
<br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
解决doget请求的中文乱码解决:
//获取请求参数
String username1 = req.getParameter("username");
//1.先以iso8859-1进行编码
//2.再以utf-8进行编码
new String(username1.getBytes("iso8859-1"),"UTF-8");
d) dopost请求的中文乱码的解决:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求体的字符集为utf-8,从而解决post请求的中文乱码问题
//也要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
System.out.println("--------doPost---------");
//获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("爱好:"+ Arrays.asList(hobby));
}
}
e)请求的转发
什么是请求的转发?
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作,叫请求转发
web配置文件
<?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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>RequestApiServlet</servlet-name>
<servlet-class>com.atguigu.Servlet.RequestApiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestApiServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>com.atguigu.Servlet.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>com.atguigu.Servlet.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
</web-app>
servlet1
package com.atguigu.Servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数(办事的材料)查看
String username = req.getParameter("username");
System.out.println("在servlet1(柜台1)中参看参数(材料),"+username);
//给材料 盖一个章 ,并传递到servlet2(柜台2)并查看
req.setAttribute("key1","柜台1的章");
//问路: Servlet2(柜台2怎么走
//请求转发必须要以斜杠打头:斜杠地址表示为:http://ip:port/工程名/ 映射到idea的web目录
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
//走向Servlet2(柜台)
requestDispatcher.forward(req,resp);
}
}
servlet2
package com.atguigu.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数(办事的材料)查看
String username = req.getParameter("username");
System.out.println("在servlet2(柜台2)中参看参数(材料),"+username);
//查看柜台1是否有盖章
Object key1 = req.getAttribute("key1");
System.out.println("柜台一是否有章?"+key1);
//开始处理自己的业务
System.out.println("servlet2 开始处理自己的业务");
}
}
f)base标签的使用
当我们点击a标签进行跳转的时候,浏览器的地址是http://localhost:8080/demo_war_exploded/a/b/c.html
跳转回去的a标签的路径是:…/…/index.html
所有相对路径在工作时候都会参照当前浏览器地址栏中的地址进行跳转,
那么参照后的地址是:http://localhost:8080/demo_war_exploded/index.html
正确的跳转路径
base标签可以设置当前页面所有相对路径工作时,参照哪个路径进行跳转
当我们使用请求转发跳转的地址是http://localhost:8080/demo_war_exploded/ForwardC
跳转回去的a标签的路径是:…/…/index.html
所有相对路径在工作时候都会参照当前浏览器地址栏中的地址进行跳转,
那么参照后的地址是:http://localhost:8080/index.html
实例:
a/b/c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<!--base标签设置页面相对路径工作时参照的路径、
href属性就是参数的地址值 -->
<base href="http://localhost:8080/demo_war_exploded/a/b/c.html">
</head>
<body>
这是a下的b的c.html界面<br/>
<a href = "../../index.html">返回主页 ../../index.html</a>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
这个是web下的index.html <br/>
<a href="a/b/c.html">a/b/c.html</a><br/>
<a href = "http://localhost:8080/demo_war_exploded/ForwardC" >请求转发:a/b/c.html</a>
</body>
</html>
ForwardC.java
package com.atguigu.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ForwardC extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("经过了ForwardC程序");
req.getRequestDispatcher("/a/b/c.html").forward(req,resp);
}
}
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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>RequestApiServlet</servlet-name>
<servlet-class>com.atguigu.Servlet.RequestApiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestApiServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>com.atguigu.Servlet.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>com.atguigu.Servlet.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ForwardC</servlet-name>
<servlet-class>com.atguigu.Servlet.ForwardC</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ForwardC</servlet-name>
<url-pattern>/ForwardC</url-pattern>
</servlet-mapping>
</web-app>
g) web中的相对路径和绝对路径
在javaweb中,路径分为相对路径和绝对路径两种,
相对路径是:
. 表示当前目录
… 表示上一级目录
资源名 表示当前目录/资源名
绝对路径:
http://ip:port/工程路径/资源路径
h)web中 / 斜杠的不同意义
在web中 / 斜杠是一种绝对路径,
/ 斜杠如果被浏览器解析 得到的地址是:http://ip:port/
/ 斜杠如果被服务器解析,得到的地址是http://ip:port/工程路径
1. /servlet1
2. servletContext.getRealPath("/");
3.request.getRequestDispatcher("/");
特殊情况:
response.sendRediect("/"); 把斜杠发送给浏览器解析,得到的http://ip:port/
6.HttpServletResponse类
a)HttpServletResponse类的作用
httpServletResponse类和httpServletRequest类一样,每次请求进来,tomcat服务器都会创建一个response对象传递给servlet程序去使用HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有相应的信息,
我们如果需要设置返回给客户端的数据,都可以通过httpServletResponse对象来进行设置
b)两个输出流的说明
字节流 getOutputStream() 常用于下载(传递二进制数据)
字符流 getWriter() 常用于回传字符串(常用)
两个流只能使用一个,
使用了字节流,就不能再使用字符流,反之亦然,否则就会报错
c) 如何往客户端回传数据
要求 : 往客户端回传 字符串 数据。
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
// 要求 : 往客户端回传 字符串 数据。
PrintWriter writer = resp.getWriter();
writer.write("response's content!!!");
}
}
d)相应的乱码解决
解决响应中文乱码问题方案一(不推荐使用!)
package com.atguigu.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(resp.getCharacterEncoding()); //默认ISO-8859-1
// 设置服务器字符集为UTF-8
resp.setCharacterEncoding("UTF-8");
//通过响应头,设置浏览器也使用utf-8字符集
resp.setHeader("Content-Type","text/html;charset=UTF-8");
//要求: 往客户端回传字符串数据
PrintWriter writer = resp.getWriter();
writer.write("阿凡达色为世人的 ");
}
}
解决响应中文乱码问题方案二 (推荐使用)
//它对同时设置服务器和客户端都是用utf-8字符集,还设置了响应头
//此方法一定要在获取数据流对象前使用才有效
resp.setContentType("text/html;charset=UTF-8");
e)请求重定向
请求重定向 是指客户端给服务器发请求,然后,服务器告诉客户端,我给你可以新的地址,你去新的地址访问,叫做请求重定向
(因为可能之前的地址可能被废弃)
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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>RequestApiServlet</servlet-name>
<servlet-class>com.atguigu.Servlet.RequestApiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestApiServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>com.atguigu.Servlet.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>com.atguigu.Servlet.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ForwardC</servlet-name>
<servlet-class>com.atguigu.Servlet.ForwardC</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ForwardC</servlet-name>
<url-pattern>/ForwardC</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ResponseIOServlet</servlet-name>
<servlet-class>com.atguigu.Servlet.ResponseIOServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ResponseIOServlet</servlet-name>
<url-pattern>/ResponseIOServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>response1</servlet-name>
<servlet-class>com.atguigu.Servlet.response1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>response1</servlet-name>
<url-pattern>/response1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>response2</servlet-name>
<servlet-class>com.atguigu.Servlet.response2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>response2</servlet-name>
<url-pattern>/response2</url-pattern>
</servlet-mapping>
</web-app>
response1.java
package com.atguigu.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("曾到此一游 response1");
//设置响应状态码302,表示重定向,(已搬迁)
resp.setStatus(302);
resp.setHeader("location","http://localhost:8080/demo_war_exploded/response2");
}
}
response2.java
package com.atguigu.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("啊哈的时刻实打实");
}
}
请求重定向的另一种方法(推荐)
resp.sendRedirect("http://localhost:8080/demo_war_exploded/response2");