zoukankan      html  css  js  c++  java
  • Servlet入门

    Servlet入门

    基本概述

        ServletServer Applet)。全称Java Servlet,未有中文译文。是用Java编写的server端程序。其主要功能在于交互式地浏览和改动数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指不论什么实现了这个Servlet接口的类,普通情况下,人们将Servlet理解为后者。

        Servlet执行于支持Java的应用server中。从原理上讲,Servlet能够响应不论什么类型的请求,但绝大多数情况下Servlet仅仅用来扩展基于HTTP协议的Webserver。

    PS:学习Servlet是学习JSP的基础。故非常重要。

    Servlet在网络中的位置


    Servlet的生命周期

    1WEBserver(Tomcat)首先会找到该Servlet并装载该Servlet

    2WEBserver(Tomcat)会创建该Servlet的实例

    3WEBserver(Tomcat)会调用实例对象的init()方法

    4WEBserver(Tomcat)创建一个封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用service()方法并将请求对象和响应对象作为參数传递进去。

    (实现是通过多线程技术)

    5WEBserver在某种情况。停止对该Servlet支持。Servlet引擎将卸载该Servlet,在卸载之前会调用Servletdestroy()方法进行销毁


    手工开发Servlet的方式

    1、在Tomcat主文件夹的webapps文件夹下建立一个web应用web1

    2、在web1下建立目录WEB-INF。在该目录中建立web.xml [web.xml能够从 ROOT/WEB-INF/web.xml拷贝

    3、在WEB-INF文件夹下建立classes文件夹(Servlet在该文件夹下开发)。建立lib文件夹

    4、在classes文件夹下开发Servlet

    5、在web.xml中配置web.xml

    6、编译Servlet文件(编译时须要将servlet-api.jar包增加环境变量classpath中,该jar包在Tomcat主文件夹的lib文件夹下)

    7、执行Tomcat

    8、訪问Servlet


    开发Servlet的三种方法

    1、实现Servlet接口

    /**
    	使用实现Servlet接口的方式开发一个Servlet
    	要求:显示当前时间
    */
    package com.pc;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.*;
    public class Servlet2 implements Servlet{
    	// 该方法用于初始化Servlet,就是把该Servlet装加载内存。该方法仅仅会被调用一次
    	public void init(ServletConfig config){
    	}
    
    	// 得到ServletConfig对象
    	public ServletConfig getServletConfig(){
    		return null;
    	}
    
    	// 该方法是服务方法,业务逻辑代码写在这
    	// 该方法每次都会被调用
    	public void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException{
    		// 在控制台输出
    		System.out.println("hello world:" + new java.util.Date().toString());
    		// 在浏览器返回
    		res.getWriter().println("hello world:" + new java.util.Date().toLocaleString());
    	}
    
    	// 该方法得到Servlet配置信息
    	public java.lang.String getServletInfo(){
    		return null;
    	}
    
    	// 销毁该Servlet,从内存中清除,该方法仅仅会被调用一次
    	public void destroy(){
    
    	}
    }

    PS:不仅要写Servlet文件。还要在web.xml中加入配置信息。配置信息格式例如以下:

        <!-- servlet部署到web.xml文件。该部署配置能够从examples下拷贝 -->
        <servlet>
            <!--servlet-name 该名字能够自己定义,可是默认就使用servlet的名字  -->
            <servlet-name>Servlet2</servlet-name>
            <!--servlet-class要指明该servlet放在那个包下的  -->
            <servlet-class>com.pc.Servlet2</servlet-class>
        </servlet>
        <!-- servlet的映射 -->
        <servlet-mapping>
            <!-- 这个servlet-name要和上面的servlet-name名字一样,这样才干匹配的上 -->
            <servlet-name>Servlet2</servlet-name>
            <!-- url-pattern 这是訪问该servlet的资源部分  默认命名规范:就是该servlet的名字-->
            <url-pattern>/Servlet2</url-pattern>
        </servlet-mapping>

    PS

    1、在classes目录下编译(当然Servlet文件也应该在这里)

    javac -encoding UTF-8 -d . Servlet文件名称.java


    2、不重新启动更新web应用

    首先,在Tomcat主文件夹的conf文件夹中找到tomcat-users.xml文件。打开它。并在<tomcat-user></tomcat-user>标签中加入例如以下语句

    <tomcat-users>
        <role rolename="manager-gui"/>
        <user username="tomcat" password="s3cret" roles="manager-gui"/>
    </tomcat-users>

    然后,在localhost:8080主界面点击,进入manager界面,找到该应用,点击reloadbutton就可以。


    2、继承GenericServlet

    /**
    	使用继承GenericServlet的方式开发一个Servlet
    */
    
    package com.pc;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.*;
    
    public class Servlet3 extends GenericServlet{
    	// 该方法是服务方法,业务逻辑代码写在这
    	// 该方法每次都会被调用
    	public void service(ServletRequest req,ServletResponse res) throws ServletException,IOException{
    		res.getWriter().println("hellow,world, GenericServle.");
    	}
    }

    PS:不仅要写Servlet文件,还要在web.xml中加入配置信息,配置信息格式例如以下:

        <servlet>
            <servlet-name>Servlet3</servlet-name>
            <servlet-class>com.pc.Servlet3</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Servlet3</servlet-name>
            <url-pattern>/Servlet3</url-pattern>
        </servlet-mapping>


    扩展:GenericServlet抽象类源代码和常见方法

    public abstract class GenericServlet implements Servlet, ServletConfig,java.io.Serializable {
        private static final long serialVersionUID = 1L;
        private transient ServletConfig config;
        public GenericServlet() {}
        @Override
        public void destroy() {}
        @Override
        public String getInitParameter(String name) {
            return getServletConfig().getInitParameter(name);
        }
        @Override
        public Enumeration<String> getInitParameterNames() {
            return getServletConfig().getInitParameterNames();
        }
        @Override
        public ServletConfig getServletConfig() {
            return config;
        }
        @Override
        public ServletContext getServletContext() {
            return getServletConfig().getServletContext();
        }
        @Override
        public String getServletInfo() {
            return "";
        }
        @Override
        //实现了Servlet的init(ServletConfig)方法,把參数config赋给了本类的成员config。然后再调用本类自己的无參的init()方法。
        public void init(ServletConfig config) throws ServletException {
            this.config = config;
            this.init();
        }
        //这种方法是GenericServlet自己的方法。而不是从Servlet继承下来的。
        //当我们自己定义Servlet时,假设想完毕初始化作用就不要再重写init(ServletConfig)方法了。而是应该去重写init()方法。

    //由于在GenericServlet中的init(ServletConfig)方法中保存了ServletConfig对象,假设覆盖了保存ServletConfig的代码,那么就不能再使用ServletConfig了。 public void init() throws ServletException {} public void log(String msg) { getServletContext().log(getServletName() + ": " + msg); } public void log(String message, Throwable t) { getServletContext().log(getServletName() + ": " + message, t); } @Override public abstract void service(ServletRequest req, ServletResponse res)throws ServletException, IOException; @Override public String getServletName() { return config.getServletName(); } }


    GenericServlet的init()方法

    在GenericServlet中,定义了一个ServletConfig config实例变量。并在init(ServletConfig)方法中把參数ServletConfig赋给了实例变量。然后在该类的非常多方法中使用了实例变量config。

    假设子类覆盖了GenericServlet的init(StringConfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说GenericServlet的实例变量config的值为null,那么全部依赖config的方法都不能使用了。

    假设真的希望完毕一些初始化操作。那么去覆盖GenericServlet提供的init()方法。它是没有參数的init()方法,它会在init(ServletConfig)方法中被调用。

    实现了ServletConfig接口

    GenericServlet还实现了ServletConfig接口。所以能够直接调用getInitParameter()、getServletContext()等ServletConfig的方法。




    3、继承HttpServlet

    /**
    	使用继承HttpServlet的方式开发一个Servlet
    	要求:显示当前时间
    */
    
    package com.pc;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.*;
    
    public class Servlet4 extends HttpServlet{
    	// 在HttpServlet中,设计者分别提供了对Post提交和Get提交的处理,默认是get提交
    	// doGet().doPost()底层也是调用service方法
    
    	// 处理Get请求
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{
    
    		resp.getWriter().println("doGet()");
    	}
    	// 处理Post请求
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
    		resp.getWriter().println("doPost()");
    	}
    }

    PS:不仅要写Servlet文件,还要在web.xml中加入配置信息。配置信息格式例如以下:


        <servlet>
            <servlet-name>Servlet4</servlet-name>
            <servlet-class>com.pc.Servlet4</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Servlet4</servlet-name>
            <url-pattern>/Servlet4</url-pattern>
        </servlet-mapping>


    扩展:HttpServlet抽象类

    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还要做还有一步简化操作。

    public abstract class HttpServlet extends GenericServlet {
        protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
            ……
        }
        @Override
        public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {
            HttpServletRequest  request;
            HttpServletResponse response;
    
            try {
                //强转
                request = (HttpServletRequest) req;
                response = (HttpServletResponse) res;
            } catch (ClassCastException e) {
                throw new ServletException("non-HTTP request or response");
            }
            //调用上面的service方法
            service(request, response);
        }
        ……
    }





    使用MyEclipse集成开发环境IDE来开发Web应用

    PS:详细的配置步骤能够參考搜索引擎。

    MyEclipse的开发文件夹结构


    Servlet细节问题

    1、一个已经注冊的Servlet能够被多次映射

      <servlet>
        <description>This is the description of my J2EE component</description>
        <display-name>This is the display name of my J2EE component</display-name>
       	<!-- servlet的注冊名 -->
        <servlet-name>MyServlet1</servlet-name>
        <!-- servlet类的全路径(包名+类名) -->
        <servlet-class>com.web1.servlet.MyServlet1</servlet-class>
      </servlet>
    <!-- 对一个已经注冊的servlet的映射 -->
      <servlet-mapping>
      <!-- servelt的注冊名 -->
        <servlet-name>MyServlet1</servlet-name>
      <!-- servlet的訪问路径 -->
        <url-pattern>/MyServlet1</url-pattern>
      </servlet-mapping>
      
      <servlet-mapping>
      <servlet-name>MyServlet1</servlet-name>
      <url-pattern>/abc</url-pattern>
      </servlet-mapping>

    2、当映射一个Servlet时。能够多层映射

      <url-pattern>/servlet/index.html</url-pattern>

    3、在Servlet使用通配符映射到URL

    有两种格式:

    第一种格式  *.扩展名  比方 *.do  *.ss

    另外一种格式  以 / 开头 同一时候以 /* 结尾  比方  /*   /news/* 

    通配符案例:

        Servlet1 映射到 /abc/* 

        Servlet2 映射到 /* 

        Servlet3 映射到 /abc 

        Servlet4 映射到 *.do 

    问题:

    1当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配。哪个servlet响应

    Servlet引擎将调用Servlet1

    2当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配。哪个servlet响应

    Servlet引擎将调用Servlet3

    3当请求URL为“/abc/a.do”时。“/abc/*”和“*.do”都匹配。哪个servlet响应

    Servlet引擎将调用Servlet1

    4当请求URL为“/a.do”时。“/*”和“*.do”都匹配。哪个servlet响应

    Servlet引擎将调用Servlet2

    5当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配。哪个servlet响应

    Servlet引擎将调用Servlet2

    在匹配的时候。要參考的标准:

        1看谁的匹配度高。谁就被选择

        2*.do 的优先级最低


    url-pattert匹配规则


    案例



    4servlet中的<load-on-startup>配置

        当须要在站点启动时,初始化一些资源时能够配置<load-on-startup>

       <servlet>
           <load-on-startup>1</load-on-startup>
       </servlet>

    PS:在servlet中如此配置即可。中间的数是整数,越小优先级越高。

    配置好了之后,在站点启动时就会调用该Servletinit()方法,所以能够在该方法中进行须要的初始化步骤,比方定时刷新,建立内存表之类的等等。


    ServletConfig对象

        该对象主要用于读取 servlet的配置信息.

    案例:

    <servlet>
        <servlet-name>ServletConfigTest</servlet-name>
        <servlet-class>com.web1.servlet.ServletConfigTest</servlet-class>
        <!-- 这里能够给servlet配置信息,这里配置的信息。仅仅能被该servlet 读取 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
      </servlet>

    怎样使用Servlet使用例如以下语句

    String encoding = this.getServletConfig().getInitParameter("encoding");

    补充说明:这样的配置參数的方式,仅仅能被某个Servlet独立使用.如希望让全部的Servlet都去读取某个參数,这样配置:

    <!-- 假设这里配置參数,可被全部servlet读取 -->
    <context-param>
       <param-name></param-name>
       <param-value></param-value>
    </context-param>

    读取全部的參数,能够使用例如以下方法:

    Enumeration<String> names=this.getServletConfig().getInitParameterNames();
    while(names.hasMoreElements()){
        String name=names.nextElement();
    	System.out.println(name);
    	System.out.println(this.getServletConfig().getInitParameter(name));
    }

    注意事项:

    1Servlet类是单例、多线程的。所以要注意线程同步情况。也就是线程不安全的。

    2Servletservice()方法,在每次响应时都会调用一次。

    3Servletinit()初始化方法,destroy()销毁方法仅仅会被调用一次。

    4Servletservice()方法。会依据client的请求方法来决定调用相应的doXXX()方法。

    5、不要重写构造方法。由于所继承的HttpServlet及其父类都已经对构造方法进行了某些初始化。当不了解这些系统自带的初始化。然后盲目使用构造方法,可能导致Servlet无法创建实例。

    6、不要重写service方法(在继承HttpServlet的情况下)。由于其内部有判别client请求方法的逻辑和一些其它逻辑。

    7、必须重写doPost()或者是doGet()方法中的一个。

    8、当想用一种逻辑去处理GetPost请求,能够採用托付机制。在doPost方法内增加this.doGet(request, response); 或者在doGet方法中增加this.doPost(request, response);

    9、继承HttpServlet开发Servlet是最经常使用的方法。

    10get提交和post提交的差别

        10.1、从安全的角度看。get < post。由于get会把提交的信息显示到地址栏。

        10.2、从提交内容大小看, get < post, get一般不要大于2kpost理论无限制。可是在实际开发中。建议不要大于64k

        10.3、从速度看,get > post,由于get只不过获取数据而已

    11Servlet的映射的后缀名不一定代表它就真的是那格式的文件。

    Servlet的多线程处理

    servlet多线程工作原理



    servlet域的线程安全情况


    servlet并发注意事项



    ----------參考《韩顺平.细说Servlet

    ----------參考《网易云课堂.Servlet技术》

  • 相关阅读:
    向cmd中添加字体的方法
    学生成绩管理系统C++
    立即抢注我的免费1T云空间
    js原型
    step3 . day8数据结构之算法
    代码练习中的bug及修改方法
    step3 . day7数据结构之二叉顺序数的创建和二叉树的栈形式遍历
    step3 . day6数据结构之非线性表 满二叉树和不完全二叉树
    step3 . day5 数据结构之线性表 栈和队的应用-球钟问题
    step3 . day4 数据结构之线性表 栈和队
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7147434.html
Copyright © 2011-2022 走看看