本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Servlet
什么是Servlet
- Servlet是JavaEE规范之一。规范就是接口
- Servlet就是JavaWeb三大组件之一(Servlet程序、Filter过滤器、Listener监听器)
- Servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端
手动实现Servlet程序
- 编写一个类去实现Servlet接口
- 实现service方法,处理请求,并响应数据
- 到web.xml中去配置Servlet程序的访问地址
创建Servlet程序
-
在src目录下新建包,包中创建Servlet实现类
-
类中继承接口,并将方法覆盖重写(alt+insert) 要注意引入了jar包,我在这里将jar包复制进web/WEB-INF/lib文件夹下(要记得右击添加到类库哦,下拉框选模块)👇
package com.hexing.servlet; import jakarta.servlet.*; import java.io.IOException; public class HelloServlet implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } // service方法是专门用来处理请求和相应的 // @param servletRequest // @param servletResponse // @throws ServletException // @throws IOException // @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("Hello Servlet 被访问了"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } } -
在web.xml文件中配置Servlet程序👇
<!-- servlet标签给Tomcat配置Servlet程序 --> <servlet> <!-- servlet-name标签 Servlet程序起一个别名(一般是类名) --> <servlet-name>HelloServlet</servlet-name> <!-- servlet-class是Servlet程序的全类名 --> <servlet-class>com.hexing.servlet.HelloServlet</servlet-class> </servlet> <!-- servlet-mapping标签给servlet程序配置访问地址 --> <servlet-mapping> <!-- servelet-name标签的作用是告诉服务器,我当前配置的地址给哪个Servlet程序使用 --> <servlet-name>HelloServlet</servlet-name> <!-- url-pattern标签配置访问地址 <br/> /在服务器解析的时候,表示地址为:http://ip:port/配置Tomcat时填写的工程路径 <br/> --> <url-pattern>/hello</url-pattern> </servlet-mapping> -
最后记住配置的地址,在运行打开网页后,在链接后跟url-pattern,即可访问servlet程序
创建过程中的常见错误:
- url-pattern中配置的路径没有以斜杠打头
- servlet-name配置的值不存在
Servlet-url到Servlet程序的访问过程
Servlet的生命周期
-
执行Servlet构造器方法
-
执行init初始化方法
第1、2步,是在第一次访问的时候创建Servlet程序会调用
-
执行service方法
第3步,每次访问都会调用
-
执行destroy销毁方法
第4步,在web工程停止的时候调用
public void HelloSevlet(){
System.out.println("1 构造器方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 初始化方法");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3 Service方法---Hello Servlet 被访问了");
}
@Override
public void destroy() {
System.out.println("4 destroy销毁方法");
}
请求的分发处理
获取请求方式
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3 Service方法---Hello Servlet 被访问了");
//类型转换(因为它有getMethod()方法)
HttpServletRequest HttpServletRequest = (HttpServletRequest) servletRequest;
//获取请求的方式
String method = HttpServletRequest.getMethod();
System.out.println(method);
if ("GET".equals(method)){
doGet();
}else if ("POST".equals(method)){
doPost();
}
}
// 做get请求的操作
public void doGet(){
System.out.println("get请求");
}
// 做post请求的操作
public void doPost(){
System.out.println("post请求");
}
通过继承HttpServlet实现Servlet程序
一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现Servlet程序
-
编写一个类去继承HttpServlet类
-
根据业务需要重写doGet或doPost方法
package com.hexing.servlet; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class HelloServlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } } -
到web.xml中配置Servlet程序的访问地址
<servlet> <servlet-name>HelloServlet2</servlet-name> <servlet-class>HelloSer</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet2</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping>
IDEA菜单生成Servlet程序
右键包→new→Create New Servlet
最后在xml文件中配置一下就欧克啦
Servlet类的继承体系
ServletConfig类
Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。
三大作用
-
获取Servlet程序的别名servlet-name的值(servletConfig.getServletName();)
-
获取初始化参数init-param(写在xml的<servlet>中)(servletConfig.getInitParameter("username");)
<init-param> <!-- 参数名 --> <param-name>username</param-name> <!-- 参数值 --> <param-value>root</param-value> </init-param> <init-param> <!-- 参数名 --> <param-name>url</param-name> <!-- 参数值 --> <param-value>jdbc:mysql//localhost:3306/test</param-value> </init-param> -
获取ServletContext对象(servletConfig.getServletContext();)
创建ServletConfig对象
ServletConfig servletConfig = getServletConfig();
一些注意事项
如果重写init方法,要注意调用父方法
super.init(config);
父方法中有this.config = config这一保存过程,将tomcat服务器提供的config对象保存在GenericServlet对象中,若重写子方法后未调用则会导致该过程丢失,出现报错
ServletContext类
- Servlet是一个接口,它表示Servlet上下文对象
- 一个web工程,只有一个ServletContext对象实例,创建多个则可当作别名,实质上还是一个对象
- ServletContext对象是一个域对象
域对象:
可以像Map一样存取数据的对象,叫域对象
这里的域指的是存取数据的操作范围
| 存数据 | 取数据 | 删除数据 | |
|---|---|---|---|
| Map | put() | get() | remove() |
| 域对象 | setAttribute() | getAttribute() | removeAttribute() |
四大作用
-
获取web.xml中配置的上下文参数context-param
<!-- context-param是上下文参数(它属于整个web工程) --> <context-param> <param-name>username</param-name> <param-value>context</param-value> </context-param> <!-- context-param是上下文参数(它属于整个web工程) --> <context-param> <param-name>password</param-name> <param-value>root</param-value> </context-param>ServletContext context = getServletConfig().getServletContext(); //或直接ServletContext context = getServletContext();该方法里面写的就是上面的形式 context.getInitParameter(param-name); -
获取当前的工程路径,格式:/工程路径
contetx.getContextPath(); -
获取工程部署后在服务器硬盘上的绝对路径(以/作为参数表示当前相对路径的根目录---工程目录)
context.getRealPath("/"); -
像Map一样存取数据
//存储,存储前key1的值为null context.setAttribute("key1","value1"); //获取 context.getAttribute("key1");
HTTP协议
请求的HTTP协议格式
客户端给服务器发送数据叫请求,服务器给客户端回传数据叫相应
请求又分为GET请求和POST请求两种
GET请求
- 请求行
- 请求方式 GET
- 请求的资源路径[+?+请求参数]
- 请求的协议的版本号 HTTP/1.0
- 请求头 key:value组成,不同的键值对,表示不同的含义
POST请求
- 请求行
- 请求方式 POST
- 请求的资源路径[+?+请求参数]
- 请求的协议的版本号 HTTP/1.0
- 请求头
- key:value 不同的请求头,有不同的含义 空行
- 请求体
常用请求头
- Accept:表示客户端可以接收的数据类型
- Accept-Languege:表示客户端可以接收的语言类型
- User-Agent:表示客户端浏览器的信息
- Host:表示请求时的服务器IP和端口号
GET请求动作与POST请求动作
GET请求
- form标签 method = get
- a标签
- link标签引入css
- Script标签引入js文件
- img标签引入图片
- iframe引入html页面
- 在浏览器地址栏中输入地址后敲回车
POST请求
- form标签 method = post
响应的HTTP协议格式
- 响应行
- 响应的协议和版本号 HTTP/1.1
- 响应状态码 200
- 响应状态描述符 ok
- 响应头
- key:value 不同的响应头,有其不同含义 空行
- 响应体:回传给客户端的数据
常用的响应码
- 200 表示请求成功
- 302 表示请求重定向
- 404 表示请求服务器已收到,但数据不存在(请求地址错误)
- 500 表示服务器已经收到请求,但是服务器内部错误(代码)
MIME(Multipurpose Internet Mail Extensions)类型说明
MIME是HTTP协议中数据类型,MIME类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应
谷歌、火狐浏览器查看HTTP协议
HttpServletRequest类
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息。
常用方法
- getRequestURI()----获取请求的资源路径
- getRequestURL()----获取请求的统一资源定位符(绝对路径)
- getRemoteHost()---获取客户端的ip地址
- getHeader()-----获取请求头
- getParameter()----获取请求的参数
- getParameterValues()----获取请求的参数(多个值的时候使用)
- getMethod()----获取请求的方式GET/POST
- setAttribute(key, value)---设置域数据
- getAttribute(key)----获取域数据
- getRequestDispatcher()----获取请求转发对象
**注意:**post请求时中文会乱码,需在获取请求参数前调用httpServletRequest.setCharacterEncoding("UTF-8");来更改编码格式
请求转发
请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作叫做转发。
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");//“/”映射到web目录
requestDispatcher.forward(req,resp);
特点:
- 浏览器地址栏没有变化
- 他们是一次请求
- 他们共享Request域中的数据
- 可以转发到WEB-INF目录下
- 不可以访问工程以外的资源
base标签
base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转
web中“/”的不同意义
在web中“/”是一种绝对路径
如果“/”被浏览器解析,得到的地址是:http://ip:port/
如果被服务器解析,得到的地址是:http://ip:port/工程路径
但如果是response.sendRediect("/"); 将“/”发送给浏览器解析,得到http://ip:port/
HttpServletResponse类
HttpServletResponse类和HttpServletRRequest类一样。每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息。
如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置。
两个输出流
- 字节流---getOutputStream();---常用于下载(传递二进制数据)
- 字符流---getWriter();---常用于回传字符串
两个流同时只能使用一个
使用了字节流,就不能再使用字符流,反之亦然,否则会报错。
//解决乱码问题方案一:
resp.setCharacterEncoding("UTF-8");//设置服务器字符集
resp.setHeader("Content-Type","text/html; charset=UTF-8");//通过响应头设置浏览器字符集
//解决乱码问题方案二:
resp.setContentType("text/html; charset-UTF-8");//它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头。但此方法一定要在获取流对象之前调用才有效
请求重定向
特点:
- 浏览器地址栏会发生变化
- 两次请求
- 不共享Request域中数据
- 不能访问WEB-INF下的资源
- 可以访问工程外的资源
请求重定向第二种实现方式
resp.sendRedirect("http://localhost:8080");
JavaEE三层架构
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。