【JavaWeb】11 Servlet

本文详细介绍了Servlet的概念、作用以及其实现方式,包括实现Servlet接口、继承GenericServlet和HttpServlet类。讲解了Servlet生命周期中的init、service和destroy方法。此外,还探讨了ServletConfig、ServletRequest、ServletResponse的重要角色,以及ServletContext的应用,如访问量统计。最后,提到了获取类路径下资源的方法。

Servlet

什么是Servlet
它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理。

  1. 接收请求数据
  2. 处理请求
  3. 完成响应

Servlet需要我们自己来编写,每个Servlet必须实现 javax.servlet.Servlet 接口。
实现Servlet有三种方式:

  • 实现javax.servlet.Servlet接口;
  • 继承javax.servlet.GenericServlet类;
  • 继承javax.servlet.http.HttpServlet类(通常选择这种);

实现Servlet接口

---------实现javax.servlet.Servlet接口,需要复写五个方法-----------

import java.io.IOException;
public class UseServlet implements Servlet{
	/*
	 * 它是生命周期方法
	 * 它会在Servlet被销毁之前调用,并且它只会被调用一次
	 */
	public void destroy(){
		System.out.println("destroy()...");
	}
	//获取Servlet配置信息
	public servletConfig getServletConfig(){
		System.out.println("getServletConfig()...");
		return null;
	}
	//获取Servlet的信息(这个方法经常闲置)
	public String getServletInfo(){
		System.out.println("getServletInfo()...");
		return "我是一个快乐的servlet";
	}
	/*
	 * 它是生命周期方法
	 * 它会在Servlet对象创建之后马上执行,并只执行一次(出生之后)
	 */
	public void init(ServletConfig servletConfig) throws ServletException{
		System.out.println("servletConfig()...");
	}
	/*
	 * 它是生命周期方法
	 * 它会被调用多次
	 * 每次处理请求都是在调用这个方法
	 */
	public void service(ServletRequest request,ServletResponse response)throws ServletException,IOException{
	System.out.println("service()...");
	}
}

servlet中的大多数方法不由我们来调用,而是由服务器(Tomcat)调用

浏览器访问Servlet

  1. 给Servlet指定一个Servlet路径(让Servlet与一个路径绑定在一起)
  2. 浏览器访问Servlet路径
配置Servlet路径
web.xml
<servlet>
	<servlet-name>XXX</servlet-name> 3.找到该名称对应Servlet
	<servlet-class>useServlet.UseServlet</servlet-class> 4.调用类
</servlet>
<servlet-mapping>
	<servlet-name>XXX</servlet-name> 2.获取名称
	<url-pattern>xxx.servlet</url-pattern> 1.浏览器输入路径
</servlet-mapping>

配置路径后,在servers找到tomcat服务器>add/remove deployments>添加项目>start
在浏览器中输入https://tomcat:8080/useServlet(项目名)/testServlet(上面配置的名称)
访问后可在控制台看到,servlet被调用时使用的方法
Servlet的生命周期方法:

  • void init(ServletConfig):创建时初始化(1次)
  • void service(ServletRequest request,ServletResponse response):每次处理请求都会被调用
  • void destroy():销毁时释放资源(1次)
    特性:
  • 单例:一个类只有一个对象,当然可能存在多个Servlet类
  • 线程不安全的,所以效率高
    Servlet类由我们来写,但对象由服务器来创建,并且由服务器来调用相应的方法

ServletConfig

web.xml
<servlet>
		<servlet-name>test2Servlet</servlet-name>
		<servlet-class>useServlet.test2Servlet</servlet-class>
		<!--初始化参数-->
		<init-param>
			<param-name>n1</param-name>
			<param-value>v1</param-value>
		</init-param>
		<init-param>
			<param-name>n2</param-name>
			<param-value>v2</param-value>
		</init-param>
</servlet>

1个ServletConfig对象,对应一段web.xml中Servlet的配置信息

  • String getServletName() 获取<servlet-name>中的内容
  • 出于安全性考虑,没有提供获取class的方法
  • String getInitParameter(String name):通过名称获取初始化参数的值
  • Enumeration getInitParameterNames():获取所有初始化参数的名称(Enumeration相当于早期的迭代器)
  • ServletContexd getServletContext():获取上下文
    使用举例:
/*
 * 它是生命周期方法
 * 它会在Servlet对象创建之后马上执行,并只执行一次(出生之后)
 */
public void init(ServletConfig servletConfig) throws ServletException{
	System.out.println("servletConfig()...");
	//通过名称获取初始化参数
	System.out.println(servletConfig.getInitParameter("n1"));
	System.out.println(servletConfig.getInitParameter("n1"));
	//获取所有初始化参数的名称
	Enumeration e=servletConfig.getInitParameterName();
	while(e.hasMoreElements()){
		System.out.println(e.nextElement());
	}
}

ServletRequest 和 ServletResponse

请求:解析http请求
回应:处理重定向等

继承GenericServlet类

GenericServlet类是上述提到的Servlet接口的空实现,因此只需继承GenericServlet类,然后复写需要自定义的方法即可。
需要注意复写初始化方法时不能复写含参数的init方法,因为这个方法中有config参数赋值的过程,复写后会导致config为空,从而接下来的调用出现异常。

@Overrride
public void init(ServletConfig config)throws ServletException{
	this.config=config;
	init(); //应该复写这个方法
}
public void init(){
	System.out.println("自定义初始化");
}

继承HttpServlet类

HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。
HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,这个方法是HttpServlet自己的方法,不是从Servlet继承来的。在HttpServlet的service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法。
在这里插入图片描述
在HttpServlet的service(HttpServletRequest,HttpServletResponse)方法会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即可。

public class UseServlet3 extends HttpServlet{
	public void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{
		System.out.println("doPost()...");
}

Servlet细节

1.工作效率高,不是线程安全的。

  • 不要在Servlet中创建成员,创建局部变量即可
  • 可以创建无状态成员
  • 可以创建有状态成员,但状态必须为只读的

2.根据标签<load-on-startup>0</load-on-startup>中非负整数从小到大的顺序决定创建Servlet的顺序
3.一个Servlet可以有多个url-pattern,用于过滤器。此时无论访问哪个路径,都可以访问到该Servlet
4.还可以在<url-pattern>中使用通配符*,可以匹配任何前缀和后缀(注意只能出现在最前或最后,不能出现在中间;且只能出现一次)
<url-pattern>/servlet/*</url-pattern>任意后缀
<url-pattern>*.do</url-pattern>任意前缀
<url-pattern>/*</url-pattern>能匹配所有URL

ServletContext

一个项目只有一个ServletContext对象。
我们可以在多个Servlet中获取这个唯一的对象,使用它可以给多个Servlet传递数据。
这个对象在tomcat启动时就创建,在tomcat关闭时才销毁

获取ServletContext

ServletConfig # getServletContext();
GenericServlet # getServletContext();
HttpSession # getServletContext()(后)
ServletContextEvent # getServletContext() (后)

  • 域对象的功能:域对象就是用来在多个Servlet中传递数据
    域对象必须有存、取数据的功能
    void setAttribute(String name,Object value)存储一个域属性(包含域属性名称、值)
    Object getAttribute(String name)通过名称获取值
    void removeAttribute(String name)移除域属性
    Enumeration getAttributeNames()获取所有域属性名称
/*
 * 演示从ServletContext中获取数据
 */
 public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
	ServletContext application=this.getServletContext();
	String name=(String)application.getAttribute("name");
	System.out.println(name);
}

获取应用初始化参数

Servlet也可以获取初始化参数,但它是局部的参数。也就是说一个Servlet只能获取自己的初始化参数。
可以配置公共的初始化参数,为所有Servlet使用,这需要使用ServletContext

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());
}

获取真实路径

//获取a.txt的真实路径:
String realPath = servletContext.getRealPath(/a.txt”)
//realPath的值为a.txt文件的绝对路径:F:\tomcat6\webapps\hello\a.txt

获取资源流,即把资源以输入流的方式获取

//获取a.txt资源流
InputStream in = servletContext.getResourceAsStream(/a.txt”)

获取指定目录下所有资源路径

Set set = context.getResourcePaths("/WEB-INF");
System.out.println(set);
//[/WEB-INF/lib/, /WEB-INF/classes/, /WEB-INF/b.txt, /WEB-INF/web.xml]

练习:访问量统计

创建一个int类型的变量,用来保存访问量,然后把它保存到ServletContext的域中,这样可以保证所有的Servlet都可以被访问到!

获取ServletContext对象,查看是否存在名为count的属性,如果存在,说明不是第一次访问,如果不存在,说明是第一次访问;

  • 第一次访问:调用Servletcontext的setAttribute()传递一个属性,名为count,值为1;
  • 第2~N次访问:调用ServletContext的getAttribute()方法获取原来的访问量,给访问量加1,再调用Servletcontext的setAttribute()方法完成设置。
public class VisitCount extends HttpServlet {	
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
 * 1.获取ServletContext对象
 * 2.获取名为count的属性
 * 	如果存在,访问量加一
 * 	如果不存在,保存名为count的属性,值为1
 */
ServletContext app=this.getServletContext();
Integer count=(Integer)app.getAttribute("count");
if(count==null)
	app.setAttribute("count",1);
else
	app.setAttribute("count",count+1);
/*
 * 向浏览器输出
 */
PrintWriter pw=response.getWriter();
pw.print("<h1>"+count+"</h1>");
}
}

获取类路径下资源

获取类路径资源,类路径对一个JavaWeb项目而言,就是/WEB-INF/classes和WEB-INF/lib每个jar包(其实就是创建项目时src文件夹下的资源)

  • Class
  • ClassLoader
先将第三方工具库中的common-io包放入项目

//1.先得到Class,再得到ClassLoader
ClassLoader cl=this.getClass().getClassLoader();
//2.得到一个InputStream
InputStream input=cl.getResourseAsStream("包名/a.txt");
或者也可以把文件放到当前class目录下,用:
Class c=this.getClass();
InputStream input=c.getResourseAsStream("a.txt");//相对当前.class文件所在目录
或者,不移动文件,用:
Class c=this.getClass();
InputStream input=c.getResourseAsStream("/a.txt");//相对classes下!
//3.读取输入流内容,转换成字符串返回
String s=IOUtils.toString(input);//这里就用了导入的jar包的类IOUtils
System.out.println(s);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值