Servlet
什么是Servlet
它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理。
- 接收请求数据
- 处理请求
- 完成响应
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
- 给Servlet指定一个Servlet路径(让Servlet与一个路径绑定在一起)
- 浏览器访问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);
本文详细介绍了Servlet的概念、作用以及其实现方式,包括实现Servlet接口、继承GenericServlet和HttpServlet类。讲解了Servlet生命周期中的init、service和destroy方法。此外,还探讨了ServletConfig、ServletRequest、ServletResponse的重要角色,以及ServletContext的应用,如访问量统计。最后,提到了获取类路径下资源的方法。
491

被折叠的 条评论
为什么被折叠?



