• 深入理解Servlet


    1、Servlet : 用java语言编写的动态资源开发技术。

    2、Servlet 特点:

    1)普通的java类,继承HttpServlet类,覆盖doGet、doPost等方法。

    2)Servlet类只能交给tomcat服务器运行。

    3、怎样使用Eclipse开发Servlet?

    1)编写一个servlet类,继承HttpServlet

    public class Servlet extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		System.out.println("This is Servlet!");
    		resp.getWriter().write("This is Servlet!");
    	}
    }

    2)配置web.xml文件

    <servlet>
      	<servlet-name>Servlet</servlet-name>
      	<servlet-class>zzuli.edu.cn.Servlet</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>Servlet</servlet-name>
      	<url-pattern>/Servlet</url-pattern>
      </servlet-mapping>

    3)访问  http://localhost:8080/FirstServlet/Servlet

    4、在web.xml中配置 <servlet>和<servlet-mapping>的作用?

    servlet容器对url的匹配过程:

    当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost:8080/FirstServlet/Servlet,我的应用上下文是FirstServlet,容器会将http://localhost:8080/FirstServlet去掉,剩下的/Servlet部分拿来做servlet的映射匹配。

    映射匹配步骤:

    1)首先在web.xml文件中查找是否有匹配的url-pattern的内容(/Servlet)

    2)如果找到匹配的url-pattern,则使用当前servlet-name的名称到web.xml文件中查询是否相同名称的servlet配置

    3)如果找到相同名称的servlet配置,则取出对应的servlet配置信息中的servlet-class内容(zzuli.edu.cn.Servlet),然后通过servlet-class里的内容,反射构造Servlet的对象,调用Servlet对象里面的方法。

    5、 Myeclipse和Eclipse中的Tomcat怎样部署项目?

    1)Myeclipse默认将项目部署到tomcat安装目录下的webapps中

    2)eclipse并不像MyEclipse默认将项目部署到tomcat安装目录下的webapps中,而是默认部署到工作目录(workspace)下的.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps中

    6、Servlet 注解

    Servlet3.0以上可以使用注解@WebServlet自动映射,不用在web.xml中配置<servlet>和<servlet-mapping>

    使用方法:编写一个servlet类,继承HttpServlet,然后在servlet上面加上@webServlet即可。

    @WebServlet("/FirstServlet2")
    public class FirstServlet2 extends HttpServlet{
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		System.out.println("This is Servlet2!");
    		resp.getWriter().write("This is Servlet2!");
    	}
    }

    注意点:@WebServlet注解括号里面必须加映射路径

    7、Sevlet的生命周期(重点)

    Servlet重要的四个生命周期方法:

    1)构造方法:创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象。只调用1次,证明servlet对象在tomcat是单实例的。

    2)init方法:创建完servlet对象的时候调用,只调用1次。

    3)service方法:每次发出请求时调用,调用n次。

    4)destroy方法:销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。

    8、伪代码演示servlet的生命周期

    Tomtcat内部代码运行:

    1、通过URL映射找到到servlet-class的内容(zzuli.edu.cn.FirstServlet)

    2、通过反射构造FirstServlet对象

         2.1 得到字节码对象

               Class clazz = class.forName("zzuli.edu.cn.FirstServlet");

         2.2 调用无参数的构造方法来构造对象

              Object obj = clazz.newInstance();  ---1.servlet的构造方法被调用

    3、创建ServletConfig对象,通过反射调用init方法

         3.1 得到方法对象

               Method m = clazz.getDeclareMethod("init",ServletConfig.class);

          3.2 调用方法

                m.invoke(obj,config);     --2.servlet的init方法被调用

    4、创建request,response对象,通过反射调用service方法

          4.1 得到方法对象

                Methodm m=clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServlet Response.class);

           4.2 调用方法

                 m.invoke(obj,request,response);      --3.servlet的service方法被调用

    5、当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法

          5.1 得到方法对象

                Method m = clazz.getDeclareMethod("destroy",null);

         5.2 调用方法

               m.invoke(obj,null);    --4.servlet的destroy方法被调用

    9、怎样证明Servlet是单例的?

    通过构造函数来证明,当多次请求(访问)servlet时,如果构造函数只被执行一次,说明servlet是单例的。

    Servlet默认是单例的,是在第一次请求被执行时创建的(懒汉式)。

    10、Servlet的自动加载

    默认情况下,servlet对象是在第一次请求被执行时创建的。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。

    怎样解决这种问题呢?

    改变servlet创建对象的时机:提前到加载web应用的时候创建!

    方法:只需要在servlet的配置信息中,加上一个<load-on-startup>即可!

    <servlet>
        <servlet-name>ServletDemo</servlet-name>
        <servlet-class>zzuli.edu.cn.ServletDemo</servlet-class>
        <!-- 让servlet对象在启动时自动加载 -->
        <load-on-startup>1</load-on-startup>  注意: 整数值越大,创建优先级越低!!
    </servlet>

    11、Servlet的多线程并发问题(重点)

    注意: servlet对象在tomcat服务器中是单实例多线程的。

    因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据,如成员变量,可能会引发线程安全问题。

    解决线程不安全问题办法:

        1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)

        2)在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步,而且尽量缩小同步代码块的范围(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。

        3)只要在servlet类中不使用共享数据,就不影响servlet的正常使用。

    线程不安全代码演示:

    /**
     * @classDesc: 功能描述:(线程不安全演示)
     */
    @WebServlet("/ServletlDemo")
    public class ServletlDemo extends HttpServlet {
    	private int i = 1;
    
    	@Override
    	public void init() throws ServletException {
    		System.out.println("ServletlDemo...init()");
    	}
    
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		resp.setCharacterEncoding("utf-8");// 内容编码,防止出现中文乱码
    		resp.setContentType("text/html;charset=utf-8");
    			// 向浏览器输出内容
    			resp.getWriter().write("这是第" + i + "次访问...");
    			i++;
    	}
    
    	@Override
    	public void destroy() {
    		System.out.println("ServletlDemo...destroy()");
    
    	}
    }

    当用两个浏览器同时访问时,会出现线程不安全问题,如下图所示

    线程安全代码:(使用synchronized)

    @WebServlet("/ServletDemo")
    public class ServletDemo extends HttpServlet {
    	private int i = 1;
    
    	@Override
    	public void init() throws ServletException {
    		System.out.println("ServletDemo...init()");
    	}
    
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		resp.setCharacterEncoding("utf-8");// 内容编码,防止出现中文乱码
    		resp.setContentType("text/html;charset=utf-8");
    		synchronized (ServetlDemo.class) {
    			// 向浏览器输出内容
    			resp.getWriter().write("这是第" + i + "次访问...");
    			try {
    				Thread.sleep(5000);
    			} catch (Exception e) {
    			}
    			i++;
    		}
    	}
    
    	@Override
    	public void destroy() {
    		System.out.println("ServletDemo...destroy()");
    	}
    }

    此时用两个浏览器同时访问,不会出现线程不安全问题

    12、ServletContext对象

    1)得到web应用上下文路径:

    ServletContext servletContext=this.getServletContext();
    String path=servletContext.getContextPath();

    2)ServletContext域对象:作用范围在整个web应用中有效!

         常用方法:

         保存数据:void setAttribute(java.lang.String name, java.lang.Object object)                             

         获取数据:java.lang.Object getAttribute(java.lang.String name)  

         删除数据:void removeAttribute(java.lang.String name)

  • 相关阅读:
    C#窗体和控件都可以收到键盘键盘消息
    C#中结构和类成员指针的内存分配
    C# 中的委托和事件
    C# 函数 传入 C++动态库中 做回调函数
    CommunityServer的登录页面
    Oracle数据库Clob字段的更新操作
    .net程序员面试题,基本上是基础概念题
    取得一段汉语的每个字的首字母
    查找CommunityServer论坛新帖提交页面的包含文件
    ASP.NET 2.0 的内部变化
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13309484.html
Copyright © 2020-2023  润新知