Servlet总结
Servlet是一个构建web程序的java技术,用来接收和影响客户端的请求
1.servlet创建方式
-
实现Servlet接口(高度的自由度)。
-
继承HttpServlet类(常用。支持http请求)
-
继承GenericServlet类(代码量最少)
继承HttpServlet类创建
配置方式:
<!--web.xml-->
<!--servlet声明-->
<servlet>
<servlet-name>loginController</servlet-name>
<servlet-class>com.xja.controller.LoginController</servlet-class>
</servlet>
<!--servlet映射信息配置-->
<servlet-mapping>
<servlet-name>loginController</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
public class LoginController extends HttpServlet{
//接收客户端发送的get请求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
//接收客户端发送的post请求
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
注解方式:(Servlet 3.0 以上的版本可以使用 @WebServlet 注解)
@WebServlet(url)
@WebServlet属性列表:
需要注意的是,使用注解方式时:
- web.xml中< web-app>标签的metadata-complete属性要为false,version大于3.0
- @WebServlet(“/find”) 中 / 不要丢失
2.servlet执行流程
用户通过客户端发送请求,请求首先到了服务器。由服务器解析请求的URL,然后再服务器的部署列表中找到对应的应用来处理这次请求。然后通过项目的web.xml(注解开发)的配置决定本地请求交给那个Servlet进行处理。Servlet执行service方法处理用户的请求,并且响应给客户端。
3.Servlet生命周期
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
3.1.init()
init()方法只调用一次,他在第一创建Servlet时,被调用,之后的每次用户请求都不会被调用.用于Servlet的初始化,在initial()中创建或加载的数据,将作用servlet的整个生命周期。
public void init(ServletConfig config) throws ServletException {
}
ServletConfig是Servlet的配置参数对象。和Servlet的关系是一对一。也就是说每一个Servlet都是对应的一个ServletConfig。它的作用就是初始化的时候把一些配置信息传递给Servlet。
原始方式设置:
<!--web.xml-->
<servlet>
<servlet-name>findController</servlet-name>
<servlet-class>com.controller.FindAllUserController</servlet-class>
<init-param>
<param-name>token</param-name>
<param-value>123000123</param-value>
</init-param>
</servlet>
@Override
public void init(ServletConfig config) throws ServletException {
String servletName = config.getServletName();
ServletContext servletContext = config.getServletContext();
System.out.println("当前Servlet的名字是:"+servletName);
//获取自定义的参数
String tokenzzz = config.getInitParameter("token");
projectToken=tokenzzz;
}
注解方式设置:(Servlet 3.0 以上的版本可以使用 @WebServlet 注解)
@WebServlet(urlPatterns = "/TestServlet1",initParams = {
@WebInitParam(name = "token",value="123000123")
}, name = "findController")
3.2.service() 方法
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。不用对 service() 方法做任何动作,只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
doGet() 和 doPost() 方法是每次服务请求中最常用的方法。
3.4.destroy()
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收
总结:默认的情况下,Servlet的实例化和初始化只会在请求第一次到达Servlet的时候执行,销毁也只会在服务器停止的时候执行,那么就说明Servlet对象只创建一次和销毁一次。从而得知Servlet对象是一个单例的。
4.Servlet的线程安全
通过Servlet的生命周期得知Servlet是一个单例的。单例的对象在多线程的情况下会出现数据共享的问题
解决方案:在Servlet的开发中定义成员变量需要谨慎。如果这个成员变量只是在初始化的时候赋值,以后不会再修改此成员变量的值,那么就可以定义成员变量。只要成员变量有被多次修改的可能性,那么就不能定义。那么就需要定义成局部变量。
5.ServletContext
ServletContext对象就是应用上下文对象。每一个应用有且只有一个ServletContext对象。它可以实现所有的Servlet之间的数据共享。
上下文对象:指的就是应用程序中的共享模块。启动web项目的时候,整个web项目中都有模块都可以共享这个上下文。它是一个全局的信息的空间。
ServletConfig是服务于Servlet本身的。
ServletContext是服务于应用本身的。
获取全局数据:
<context-param>
<param-name>token</param-name>
<param-value>123000321</param-value>
</context-param>
public void init(ServletConfig config) throws ServletException {
ServletContext servletContext = config.getServletContext();
String token = servletContext.getInitParameter("token");
projectToken=token;
}
数据共享:
public class LoginController extends HttpServlet{
private ServletConfig config;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = config.getServletContext();
//把数据根据KV的方式放入到域中
servletContext.setAttribute("name","张三");
}
public void init(ServletConfig config) throws ServletException {
this.config=config;
ServletContext servletContext = config.getServletContext();
String token = servletContext.getInitParameter("token");
projectToken=token;
}
}
//模仿源码找到解决方案
//根据Key获取域中的数据 从而完成数据共享
String name = (String)servletContext.getAttribute("name");
6.映射问题
解决多个请求映射同一个Servlet
解决方案1:配置
<servlet>
<servlet-name>userController</servlet-name>
<servlet-class>com.controller.UserController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userController</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>userController</servlet-name>
<url-pattern>/delete</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>userController</servlet-name>
<url-pattern>/update</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>userController</servlet-name>
<url-pattern>/findall</url-pattern>
</servlet-mapping>
解决方案2:注解
@WebServlet({"/add","/delete","/update","/findall"})
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String requestURI = req.getRequestURI();
String str = requestURI.substring(requestURI.lastIndexOf("/") + 1);
switch (str){
case "add" :
break;
case "delete" :
break;
case "update" :
break;
case "findall" :
break;
}
}