什么是Servlet
- JavaWeb开发的基石,与平台无关的服务器组件
- 运行在Servlet容器/Web应用服务器/Tomcat
- 负责与客户端通信
架构
Web Browser —— HTTP Server —— Servlets Program —— Database
功能
-
属于“控制层”
-
创建并返回基于客户端请求的HTML动态页面
-
与数据库进行通信
-
与JSP不同的是,Servlet注重数据处理,JSP注重页面处理
总而言之,就是:可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
使用
- Servlet本身是一组接口,位于javax.servlet(java的拓展包)
package javax.servlet;
import java.io.IOException;
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
- 我们要自定义一个类,并且实现servlet的接口
- 抽象方法,缺一不可
- 这个类就具备了接收客户端请求并作出响应的功能
- index.jsp是localhost:8080/下的默认资源
- Servlet实现类编译后在out/artifacts/…/WEB-INF文件夹下的,运行需要加映射
- 要保证外部库的Tomcat包下有:
- jsp-api.jar
- servlet-api.jar
配置
-
客户端浏览器没有办法访问编译后的servlert文件,它在web里头,只能映射来间接访问
-
方式一:基于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>MyServlet</servlet-name>
<servlet-class>com.microsoft.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
</web-app>
-
本质:映射关联【name —— class —— url】
-
访问:localhost:8080/myservlet
-
缺点:不直观,维护麻烦
-
方式二:基于注解的方式——直接映射,更加直接(更推荐这个)
@WebServlet("/myservlet")
public class MyServlet implements Servlet {}
servlet对象创建——public MyServlet()
- 我们看不到,但它不是静态!
- 实际上,是Tomcat容器用反射机制自动为我们创建的,所以web.xml配置需要全类名
- 反射创建对象调用的是“无参”
- 底层原理:
- 编译servlet类文件,把字节码文件加载到方法区内,作为模板(获取运行时类)
- 本质:静态类加载到JVM内存
- 利用模板创建对象
- 动态创建,不同于new
- 编译servlet类文件,把字节码文件加载到方法区内,作为模板(获取运行时类)
初始化处理——init()
-
getServletConfig()
- getServletName()——获取类名
- getInitParameter(String s)——获取init参数的值,在web.xml的servlet中配置
- 应用:默认设置用户名、密码、用户类型(super user)
<servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.microsoft.servlet.MyServlet</servlet-class> <init-param> <param-name>username</param-name> <param-value>admin</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>123456</param-value> </init-param> <init-param> <param-name>type</param-name> <param-value>super</param-value> </init-param> </servlet>
- getInitParameterNames()——返回一个Enumeration容器,装的初始化参数
- 类似Set<>容器
- 通过遍历,拿出param-name,可以配合getInitParameter(element)拿出param-value
@Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("初始化加载中..."); System.out.println("ServletName = " + servletConfig.getServletName()); //this.username = servletConfig.getInitParameter("username"); Enumeration<String> enumeration = servletConfig.getInitParameterNames(); while(enumeration.hasMoreElements()){ String element = enumeration.nextElement(); System.out.println(element+":"+servletConfig.getInitParameter(element)); } }
-
getServletContext()——返回ServletContext对象(也是个接口),它是Servlet的上下文,整个Servlet的管理者,通过它,可以拿到整个服务的信息。【最常用】
-
getServletContext()常用API:
- getContextPath()——返回Deployment里配置的Application context
- getServerInfo()——返回服务器信息
- …
-
ServletContext与ServletConfig的区别:
- ServletConfig侧重当前Servlet实例里的配置信息,一个Servlet对应一个ServletConfig
- ServletContext侧重全局的信息,作用于整个web应用,一个web应用对应一个ServletContext,多个Servlet对应一个ServletContext
- 两者都有getInitParameter(),但是ServletContext是这样配置的:
<context-param>
<param-name>username</param-name>
<param-value>all</param-value>
</context-param>
- 说白了,ServletContext是全局对象,ServletConfig是局部对象
核心方法——service()
-
真正有用!!!一般开发都写这个!!!
-
功能:接收请求,作出响应,处理业务逻辑
// 核心:处理业务逻辑
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
String id = servletRequest.getParameter("id");
if(id!=null) {
System.out.println("我是Servlet,我已经接收到客户端发来的请求,参数是" + id);
}
servletResponse.setContentType("text/html;charset=UTF-8");
servletResponse.getWriter().write("客户端你好,我接收到你的请求了!");
}
-
接收请求
-
接收参数?id=xxxxx
-
怎么传参?http://localhost:8080/myservlet?id=1
-
-
作出响应
- 设置文件格式、编码格式
- 拿笔,写内容
生命周期
-
创建——无参构造器
-
Tomcat会先在容器中检测有没有servlet实例化对象
-
没有,反射动态机制创建一个
-
有,还用原来那个(内存问题——单例模式)
-
-
初始化——init()
- 一般不用
-
使用——service()
- 访问几次,执行几次
- 但servlet对象只有一个
-
回收——destroy()
- 关闭Tomcat,停止服务,释放当前对象所占用的资源
- GC回收
-
【单例模式】模拟执行
- 第一次访问:无参构造+init()+service()
- 第二次访问:service()
- 。。。
- 第n次访问:service()
- 关闭服务器:destroy()
层次结构
Servlet【接口】 —> GenericServlet(通用Servlet )【抽象类】 —> HttpServlet【抽象类】
-
HTTP常用请求:(类似增删改查)
- GET——读取【查】
- POST——保存【增】
- PUT——修改【改】
- DELETE——删除【删】
-
HttpServlet的优势在于——清晰地区分开了请求类型
package com.microsoft.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("GET");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("POST");
}
}
- 不同类型,不同的业务处理
- GenericServlet 实现Servlet接口,同时为它的子类**屏蔽了不常用的方法**,子类只需要重写service() 即可
- HttpServlet 继承GenericServlet抽象类,根据请求类型进行**分发处理**
- 开发者自定义的Servlet类,只需要继承HttpServlet 即可,重新doGet()、doPost()
调试工具
- Postman
- 下载链接:https://www.postman.com/
其他
-
能try/catch处理就处理,别老throws抛掉,抛到最后就是把压力给JVM
-
servlet在Java环境加载不到,在web环境才可以(除非自己导servlet-api的jar包)