如上图:浏览器通过url访问服务器端,此时服务器端的service() 方法就会执行。
执行原理:
1、被创建:执行init方法,只执行一次。
说明:该方法执行后,就会创建Servlet对象,并且我们也可以在该方法中加载资源。
那么什么时候才会调用init
方法,创建Servlet对象呢??
① 默认情况下第一次访问该类时,Servlet被创建;
② 我们也可以根据自己的需求,配置指定Servlet创建时机。
配置方式,在
标签下配置如下参数:
// 默认值就是 -1
<load-on-startup>-1load-on-startup>
// 设置值0或者正整数
<load-on-startup>1load-on-startup>
注意:
Servlet的init
方法只执行一次,说明内存中只存在一个Servlet对象,Servlet是单例。
问题:多个用户同时访问时,可能存在线程安全问题。
解决线程安全问题:尽量不要再Servlet中定义成员变量。即使定义了成员变量,也不要对齐修改值。
2、提供服务:执行service方法,执行多次。每次访问Servlet时,都会被执行。
3、被销毁:执行destory方法,只执行一次
说明:在服务器正常关闭时执行,执行一次。
在Servlet被销毁之前执行,一般用于释放资源。
创建一个类,被实现Servlet接口中的方法。
public class Demo2_servlet implements Servlet {
/**
* @description: 初始化方法,在servlet被创建时执行。只会执行一次。
* @param servletConfig
* @return: void
* @author: King
* @date: 2019-03-12 13:59
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init.........");
}
/**
* @description: 获取servlet的配置对象 ServletConfig
* @param
* @return: javax.servlet.ServletConfig
* @author: King
* @date: 2019-03-12 14:08
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* @description: 提供服务的方法,每一次servlet被访问时都会执行。
* @param servletRequest
* @param servletResponse
* @return: void
* @author: King
* @date: 2019-03-12 14:00
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service.........");
}
/**
* @description: 获取servlet一些信息,例如版本、作者等。
* @param
* @return: java.lang.String
* @author: King
* @date: 2019-03-12 14:09
*/
@Override
public String getServletInfo() {
return null;
}
/**
* @description: 销毁。在服务器正常关闭时执行,执行一次。
* @param
* @return: void
* @author: King
* @date: 2019-03-12 14:01
*/
@Override
public void destroy() {
System.out.println("destroy.........");
}
}
load-on-startup标记容器是否在启动的时候实例化并调用其init()方法的优先级。
它的值表示servlet应该被载入的顺序
HttpServlet:对http协议的封装
定义类继承HttpServlet,重写doGet/doPost等其他请求方法,然后做出逻辑判断。如下代码:
@WebServlet("/demo3")
public class Demo3_Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost....");
}
}
url-pattern :表示Servlet资源访问路径
一个Servlet可以定义多个访问路径
以“/”开头,以字母(非”*”)结束。比如:单层路径/xxx
、多层路径/xxx/xxx
比如:
<servlet-mapping>
<servlet-name>myServletservlet-name>
<url-pattern>/demo.htmlurl-pattern>
<url-pattern>/demo1url-pattern>
<url-pattern>/user/accounturl-pattern>
servlet-mapping>
当访问http://localhost:8080/demo.html
、http://localhost:8080/demo1
、http://localhost:8080/user/account
路径时,都可以访问该myServlet。
以* 开头,以扩展名结束。比如:*.do
、*.jsp
等等。
<servlet-mapping>
<servlet-name>myServletservlet-name>
<url-pattern>*.dourl-pattern>
<url-pattern>*.jspurl-pattern>
<url-pattern>*.htmlurl-pattern>
servlet-mapping>
当访问http://localhost:8080/findAll.do
、http://localhost:8080/index.jsp
、http://localhost:8080/login.html
路径时,都可以访问该myServlet。
匹配范围:可以匹配所有请求,包括静态资源。
分析:tomcat会将所有的请求全部交由对应的Servlet进行处理,最终都会在这个Servlet中结束。也就是说,如果我们访问.jsp
等静态页面,也会被Servlet拦截,从而导致无法访问该静态页面。
以 / 开头,并以 * 结尾,即/*
。
<servlet-mapping>
<servlet-name>myServletservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
当访问http://localhost:8080/xxx.do
、http://localhost:8080/xxx.jsp
、http://localhost:8080/xxx.html
路径时,都可以访问该myServlet。
会拦截除jsp的所有请求,交由Servlet处理。但不会拦截jsp。
/
:默认匹配
<servlet-mapping>
<servlet-name>myServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
如上,当我们访问http://localhost:8080/test.jsp
时,不会被Servlet拦截,而是直接访问test.jsp。
为什么不会拦截jsp文件?
因为tomcat做了如下配置
tomcat默认配置/conf/web.xml:
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>jspservlet-name>
<url-pattern>*.jspurl-pattern>
<url-pattern>*.jspxurl-pattern>
servlet-mapping>
当访问http://localhost:8080/随意输入
,都可以访问该myServlet。
注意:被该注解修饰的Servlet被访问的优先级很低,只有在找不到【输入的路径对应的Servlet】时,才会访问该Servlet。
当一个url与多个servlet的匹配规则可以匹配时,则按照 精确路径 > 最长路径 > 扩展名 > 缺省匹配 这样的优先级匹配到对应的servlet。
在SpringMVC的web.xml中如下配置时:
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
/* : 如果访问路径中有 .jsp
,那么该访问会被 SpringMVC 的 DispatcherServlet 处理,当做一个 Controller 去匹配,匹配不到就会返回404。
/ : 如果访问路径中有.jsp
,将直接jsp,不经过 SpringMVC 的 DispatcherServlet ,不会被他拦截。
web.xml
<servlet>
<servlet-name>demo1servlet-name>
<servlet-class>cn.king.web.servlet.Demo1_servletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>demo1servlet-name>
<url-pattern>/demo1url-pattern>
<url-pattern>/demo2url-pattern>
servlet-mapping>
版本要求:Servlet 3.0及其以后的版本
我们可以不在web.xml中配置项目的访问路径、资源路径,我们可以采用更简便的方式:注解,来配置。
使用方式:
在类上使用@WebServlet注解,进行配置。
例如:
匹配单一路径、匹配多个路径
@WebServlet("/demo") 匹配单一路径
@WebServlet({"/demo4","/d4","/dm4"}) 匹配多个路径
public class ServletDemo implements Servlet {}