HttpServlet
HttpServlet概述
HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。
HttpServlet覆盖了service()方法
HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)
方法,这个方法是HttpServlet自己的方法,不是从Servlet继承来的。在HttpServlet的service(ServletRequest,ServletResponse)
方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法,这说明子类可以去覆盖service(HttpServletRequest,HttpServletResponse)
方法即可,这就不用自己去强转请求和响应对象了。其实子类也不用去覆盖service(HttpServletRequest,HttpServletResponse)
方法,因为HttpServlet还要做另一步简化操作。
doGet()/doPost()
在HttpServlet的 service(HttpServletRequest,HttpServletResponse)
方法会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即可。
Servlet细节
-
不要在Servlet中创建成员变量,创建局部变量即可。
-
可以创建无状态成员。
-
可以创建有状态的成员,但状态必须为只读的。
Servlet与线程安全
因为一个类型的Servlet只有一个实例对象,那么就有可能会现同一个Servlet同时处理多个请求,那么Servlet是否为线程安全的呢?答案是:“不是线程安全的”。这说明Servlet的工作效率很高,但也存在线程安全问题。
所以我们不应该在Servlet中随便创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。
让服务器在启动时就创建Servlet
默认情况下,服务器会在某个Servlet第一次收到请求时创建它。也可以在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet。
<servlet>
<servlet-name>hello1</servlet-name>
<servlet-class>com.coydone.servlet.Hello1Servlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello1</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>com.coydone.servlet.Hello2Servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello3</servlet-name>
<servlet-class>com.coydone.servlet.Hello3Servlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello3</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
在<servlet>
元素中配置<load-on-startup>
元素可以让服务器在启动时就创建该Servlet,其中<load-on-startup>
元素的值必须是大于等于的整数,它的使用是服务器启动时创建Servlet的顺序。上例中,根据<load-on-startup>
的值可以得知服务器创建Servlet的顺序为Hello1Servlet、Hello2Servlet、Hello3Servlet。
ServletContext
一个项目只有一个ServletContext对象。我们可以在n个Servlet中来获取这个唯一的对象,使用它可以给多个Servlet传递数据。这个对象在Tomcat启动时就创建,在Tomcat关闭时才会销毁。
ServletContext概述
指实际存在的一个Web应用,所以web程序发布服务器上面,服务器产生一个ServletContext服务器会为每个应用创建一个ServletContext对象:
-
ServletContext对象的创建是在服务器启动时完成的;init()初始化的方法。
-
ServletContext对象的销毁是在服务器关闭时完成的。destroy()。
ServletContext对象的作用是在整个Web应用的动态资源之间共享数据。例如在AServlet中向ServletContext对象中保存一个值,然后在BServlet中就可以获取这个值,这就是共享数据了。
服务器启动的时候,为每个WEB应用创建一个单独的ServletContext对象,我们可以使用这个对象存取数据,用这个对象存取的数据可以在整个WEB应用中获得。可以使用如下方法存取数据:
-
setAttribute(String name,Object object):向ServletContext中存数据。
-
getAttribute(String name):从ServletContext中取数据。
-
removeAttribute(name):从ServletContext中移除数据。
ServletContext 类的四个作用:
-
获取 web.xml 中配置的上下文参数 context-param。
-
获取当前的工程路径,格式:/工程路径。
-
获取工程部署后在服务器硬盘上的绝对路径。
-
像 Map 一样存取数据。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1、获取 web.xml 中配置的上下文参数context-param
ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println("context-param 参数 username 的值是:" + username);
System.out.println("context-param 参数 password 的值是:" + context.getInitParameter("password"));
// 2、获取当前的工程路径,格式: /工程路径
System.out.println( "当前工程路径:" + context.getContextPath() );
// 3、获取工程部署后在服务器硬盘上的绝对路径
// / 斜杠被服务器解析地址为:http://ip:port/工程名/ 映射到 IDEA 代码的 web 目录
System.out.println("工程部署的路径是:" + context.getRealPath("/"));
System.out.println("工程下 css 目录的绝对路径是:" + context.getRealPath("/css"));
System.out.println("工程下 imgs 目录 1.jpg 的绝对路径是:" + context.getRealPath("/imgs/1.jpg"));
}
web.xml 中的配置:
<!--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 像 Map 一样存取数据:ContextServlet1 代码
public class ContextServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取 ServletContext 对象
ServletContext context = getServletContext();
System.out.println(context);
System.out.println("保存之前: Context1 获取 key1 的值是:"+ context.getAttribute("key1"));
context.setAttribute("key1", "value1");
System.out.println("Context1 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));
}
}
ContextServlet2 代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
ServletContext context = getServletContext();
System.out.println(context);
System.out.println("Context2 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));
}
获取ServletContext
ServletConfig#getServletContext();
GenericServlet#getServletContext();
HttpSession#getServletContext()
ServletContextEvent#getServletContext()
在Servlet中获取ServletContext对象:
- 在void init(ServletConfig config)中:
ServletContext context = config.getServletContext();
,ServletConfig类的getServletContext()方法可以用来获取ServletContext对象。
在GenericeServlet或HttpServlet中获取ServletContext对象:
- GenericServlet类有getServletContext()方法,所以可以直接使用this.getServletContext()来获取。
public class MyServlet implements Servlet {
public void init(ServletConfig config) {
ServletContext context = config.getServletContext();
}
...
}
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
ServletContext context = this.getServletContext();
}
}
域对象的功能
ServletContext是JavaWeb四大域对象之一:PageContext、ServletRequest、HttpSession、ServletContext。
所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,ServletContext对象用来操作数据的方法:
-
void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute(“xxx”, “XXX”),在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同。
-
Object getAttribute(String name):用来获取ServletContext中的数据,当前在获取之前需要先去存储才行,例如:
String value = (String)servletContext.getAttribute(“xxx”);
,获取名为xxx的域属性。 -
void removeAttribute(String name):用来移除ServletContext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做。
-
Enumeration getAttributeNames():获取所有域属性的名称。
获取应用初始化参数
Servlet也可以获取初始化参数,但它是局部的参数。也就是说,一个Servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个Servlet准备。
可以配置公共的初始化参数,为所有Servlet而用,这需要使用ServletContext才能使用。还可以使用ServletContext来获取在web.xml文件中配置的应用初始化参数。注意,应用初始化参数与Servlet初始化参数不同。
web.xml
<web-app ...>
...
<context-param>
<param-name>paramName1</param-name>
<param-value>paramValue1</param-value>
</context-param>
<context-param>
<param-name>paramName2</param-name>
<param-value>paramValue2</param-value>
</context-param>
</web-app>
ServletContext context = this.getServletContext();
String value1 = context.getInitParameter("paramName1");
String value2 = context.getInitParameter("paramName2");
System.out.println(value1 + ", " + value2);
Enumeration names = context.getInitParameterNames();
while(names.hasMoreElements()) {
System.out.println(names.nextElement());
}
ServletConfig类
ServletConfig类的作用:
-
可以获取 Servlet 程序的别名 servlet-name 的值 。
-
获取初始化参数 init-param。
-
获取 ServletContext 对象。
web.xml 中的配置:
<!-- servlet 标签给 Tomcat 配置 Servlet 程序 -->
<servlet>
<!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全类名-->
<servlet-class>com.coydone.servlet.HelloServlet</servlet-class>
<!--init-param 是初始化参数-->
<init-param>
<!--是参数名-->
<param-name>username</param-name>
<!--是参数值-->
<param-value>root</param-value>
</init-param>
<!--init-param 是初始化参数-->
<init-param>
<!--是参数名-->
<param-name>url</param-name>
<!--是参数值-->
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
</servlet>
<!--servlet-mapping 标签给 servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用-->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern 标签配置访问地址 <br/> / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/> /hello 表示地址为:http://ip:port/工程路径/hello <br/> -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
Servlet 中的代码:
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init 初始化方法");
// 1、可以获取 Servlet 程序的别名 servlet-name 的值
System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName());
// 2、获取初始化参数 init-param System.out.println("初始化参数 username 的值是;" + servletConfig.getInitParameter("username"));
System.out.println("初始化参数 url 的值是;" + servletConfig.getInitParameter("url"));
// 3、获取 ServletContext 对象
System.out.println(servletConfig.getServletContext());
}
评论区