Servlet
一、Servlet简介
什么是servlet?
servlet是在服务器上运行的类文件,由服务器进行调用。调用的过程是:由客户端
发出一个请求到服务器,服务器端在接收到请求后就会进行处理,如果请求的资源是个servlet
那么服务器就会根据相应的配置文件去找到这个servlet并运行,然后将运行后的结果返回到客户端
,完成服务器的响应。
servlet在web.xml中的配置:
<servlet> <servlet-name>servlet</servlet-name> <servlet-class>com.guigu.ServletTest.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
Servlet简单介绍:servlet的框架的核心是javax.servlet.Servlet的接口,所有的servlet都必须实现这一接口。在servlet接口中定义了五个方法,其中三个方法代表了servlet的生命周期。
Init方法:用于初始化servlet对象
Service方法:用于响应客户的请求
Destroy方法:当servlet对象退出生命周期时,负责释放占用的资源
首先是GenericServlet类实现了接口servlet、servletConfig、还有Serializable类,而HttpServlet类又继承了GenericServlet类,我们所写的servlet只实现了几个方法,例如:doGet,doPost方法,但是实际的本质并非如此。按照servlet规范,所有的Servlet都必须实现Servlet接口,而servlet的接口的方法实现的话又都非常的繁琐,所以Servlet规范为了简化开发人员的工作量,所有又定义了个GenericServlet由它来实现了servlet的接口,HttpServlet又是它的子类,所有根据java语言的继承与实现的特征,所以我们写的Servlet最终也去实现了servlet的接口。所以最符合的说法是:Servlet都会直接或间接的实现Servlet的接口。其中最底层的一些工作让HttpServlet去为我们实现,而我们只需要关注我们要去实现的方法就可以了,比如doPost或者doGet方法。
因此如果我们Servlet去继承了HttpServlet类,那么就不必去实现service方法,因为HttpServlet已经帮我们来进行了实现,service方法的逻辑是:首先从HttpServletRequest对象中获取HTTP请求方式的信息,然后再根据请求方式调用相应的方法。例如:如果请求方式为GET,则调用doGet方法,如果请求方式为POST,则调用doPost方法。
二、Servlet生命周期
Servlet生命周期可以分为三个阶段:1、初始化阶段2、响应客户阶段3、终止阶段
在javax.servlet.Servlet接口中定义了三个方法init(),service(),destroy(),它们将分别在Servlet不同的阶段被调用。
这些是常见的生存周期方法,且会以下列顺序调用:
- servlet被构造,然后用init方法将其初始化。
- 任何从客户端到service的方法被处理。
- servlet被剔除 service, 然后被 destroy方法破坏,然后投入到垃圾箱,被终结。
三、Servlet的初始化阶段
在下列时刻Servlet容器装载Servlet:1、servlet容器启动后会自动装载某些Servlet 2、在servlet容器启动后,客户首次向Servlet容器发出请求。3、Servlet的文件被更新后,重新装载Servlet。
Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化,在Servlet生命周期中init()方法只会被调用一次。
四、Servlet的响应客户请求阶段
对于到达Servlet容器的客户请求,Servlet会创建针对这个请求的HttpRequest对象和HttpResponse对象,然后调用Servlet的service方法。Service方法从ServletRequest对象获得客户请求信息、处理该请求,并通过ServletResponse对象向客户端返回响应结果。
五、Servlet的终止阶段
当Web应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet的新实例时,Servlet容器会调用Servlet的destory方法。在destory方法中,可以释放Servlet所占用的资源。
六、Servlet的多线程同步问题(重要)
Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。
由于Servlet/JSP默认为是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程同步问题。
如果在编写Servlet/JSP程序时不注意到多线程同步问题,这往往造成编写的程序在少量用户访问时没有问题,而在并发用户上升到一定值时,就会经常出现一些莫名其妙的问题,对于这类随机性的问题调试难度也将会非常的大。
会导致同步问题的HelloServlet
StringuserName = null; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { userName = request.getParameter("userName"); if(userName==null){ userName = "我的朋友"; } try { System.out.println("当前线程的名称:"+Thread.currentThread().getName()); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } response.setContentType("text/html;charset=GB2312"); PrintWriter out = response.getWriter(); out.print("<html><head><title>测试HelloServlet</title></head><body>"); out.print("<p>"+userName+"</p></body></html>"); out.close(); }
解决线程同步问题的方案:
1、 Servlet实现javax.servlet.Single.ThreadModel接口,此时Servlet容器将保证Servlet实例将以单线程的方式运行,也就是说同一时刻,只会有一个线程执行这个Servlet的Service()方法。但是这样会导致服务器以极低的效率运行服务,因此不推荐这种方式。
2、 去除实例变量,使用局部变量(推荐使用此种方式)。
3、 使用同步代码块,synchronized{}(不推荐使用这种方式)
七 ServletContext接口
ServletContext和Web应用关系
当Servlet容器启动Web应用时,并为每个Web应用创建唯一的ServletContext对象。你可以把Servletcontext看成是一个Web应用的服务器端组件的共享内存。在ServletContext中可以存放共享数据,它提供了读取或设置共享数据的方法:
1、 setAttribute(String name,Object object)把一个对象和一个属性名绑定,将这个对象存储在ServletContext中。
2、 getAttribute(String name),根据给定的属性名返回绑定的对象。
八、Web应用何时被启动
当servlet容器启动时,会启动所有的web应用
通过控制台启动Web应用。