Servlet入门篇

Servlet初学者指南
这篇博客介绍了Servlet的基础知识,包括在Tomcat中创建Web应用、Servlet的生命周期、HttpServlet的使用,以及Servlet配置、线程安全问题、ServletConfig和ServletContext的应用。内容详细,适合初学者学习。
今天刚接触Servlet,并作了如下总结,如有哪里错误请指教!(PS:后面的知识还有持续更新,如有需要的朋友,请关注······)

1. 如何创建一个你的第一个servlet?

**在tomcat中新建一个web应用,然后在web应用中新建一个web-inf/classes目录。
//**在classes目录中新建一个FirstServlet,例如:
package com.Cecilia.servlet;
import java.io.*;
import javax.servlet.*;
public class FirstServlet extends GenericServlet{
public void service(ServletRequest req,ServletResponse res)throws Exception{
    OutputStream out=res.getOutStream();
    out.write("Hello Servlet!".getBytes());
   }
}
//**set classpath-%classpath%;//配置路径
  //导入servlet.jar;//编译servlet
//**在wWEB-INF目录中新建一个web.xml文件,配置servlet的对外访问路径;
//**启动tomcat完成。
看到这里,相信大家对Servlet有个大致的轮廓了解,那么接下来让我们站起来从整体上来看看Servlet,如下图:

Servlet
2. servlet生命周期

对于每一个生命而言,都会存在生老病死,当然,Servlet也一样,它在开发的过程中也存在生命周期,随着用户访问时出生,又随着Web应用关闭而死亡,那么Servlet的整个生命周期具体是如何的呢?
**servlet对象是用户访问时第一次创建servlet对象驻留在内存中,响应后续服务请求。
**servlet的使用过程中,需要调用初始化init()、request()、response()方法;
**在web服务器被关闭或者web应用被删除的情况下,servlet就会被摧毁的时候,这时需要调用destroy()方法。
另外还提供一个 Servlet的UML原理图,如下:

Servlet的UML原理图

3.Servlet接口两个实现类

GenericServlet、HttpServlet

HttpServlet指能够处理HTTP协议请求的Servlet,在原有的Servlet接口基础上添加了一些与HTTP协议请求的处理方法,比Servlet接口更强大,通常使用HttpServlet接口,在实现Servlet接口时,覆写了service的方法,该方法体内的代码会自动判断用户的请求方式,如GET请求就会调用GET方法、POST请求就会调用POST方法,开发人员在编写Servlet时,不需要覆写service方法,只需要覆写DoGet犯法或者doPost方法。
**细节部分
***Servlet程序能够被外界访问,可以在web.xml中使用和来完成servlet程序映射到一个URL地址上,用于指定servlet的注册名称,用于指定servlet的对外访问路径;
***Servlet注册使用,包含两个主要的子元素:用于设置servlet的注册名称,用于设置Servlet的完整类名;
*同一个Servlet可以被映射到多个URL地址上,即多个元素的子元素的设置值可以是同一个Servlet的注册名;
**URL地址使用通配符的两种方式:
一种格式是:“.扩展名”,一种格式是:必须是/开头,以“/”结尾;
*当多个servlet都存在匹配问题时,需要考虑这些映射关系的优先级。
eg:下面有一些映射关系:

    1. Servlet1 映射到/abc/*
    1. Servlet2 映射到/*
    1. Servlet3 映射到/abc
    1. Servlet4 映射到 *.do

      1. 当请求的URL为“/abc/a.html”,/abc/和/都匹配,Servlet引擎将调用Servlet1;
      1. 当请求的URL为“/abc”,/abc/*和/abc都匹配,Servlet引擎将调用Servlet3;
      1. 当请求的URL为“/abc/a.do”,/abc/.do都匹配,Servlet引擎将调用Servlet1;
      1. 当请求的URL为“/a.do”,/abc/.do都匹配,Servlet引擎将调用Servlet2;
      1. 当请求的URL为“/XXX/yyy/a.do”,/.do都匹配,Servlet引擎将调用Servlet2;
      *(PS:当*.扩展名的形式优先级最低)
      ***Servlet是一个供其他Java程序调用的Java类,不能独立运行
      *针对客户端的多次servlet请求,只会创建一个serlet实例对象,一旦创建,他就会驻留在内存中,为后续其他请求服务,直至web容器退出,servlet才会被摧毁;
      *在servlet的生命周期内,servlet的init方法只会被调用一次,而对一个servlet的每次访问请求都会导致servlet引擎的service方法,对于每次请求,Servlet引擎都会创建一个HttpServletRequest请求对象和一个新HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用servlet的service()方法,service方法再根据请求方式分别调用doGet或者DoPost()方法。

      4. Servlet的线程安全问题

      *出现线程安全问题的原因:
      当多个客户端并发访问同一个servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用servlet的service方法,因此在service的内部访问同一个共享资源时,就可能会引发线程安全问题。
      **解决线程安全的方法
      **SingThreadModel接口—实现SingThreadModel接口,那么servlet引擎将会以单线程模式来调用service方法,SingThreadModel接口中未定义任何方法(类似的接口还有Serializable序列化、Cloneable克隆接口等),只需要实现类添加继承SingThreadModel接口声明就行,这实现SingThreadModel接口的servlet类任然可以支持多线程并发访问,其采用的方法就是产生多个servlet实例对象,并发的每一个线程分别调用一个独立的servlet的对象,这样能够实现servlety引擎创建多个servlet实例对象,能够从侧面上解决线程安全问题,但是不能真正意义上解决多线程同时访问同一个Servlet实例对象的问题;(不过这种方式已经过时!!)

      5. ServletConfig API

      *当servlet配置初始化参数后,web容器在创建servlet实例化对象时,会自动将这些参数封装到ServletConfig对象中,并调用servlet的init方法时,将ServletConfig对象传递给servlet,进而开发者就可以通过Servlet API获得当前的servlet的初始化参数。
      eg:
      //得到指定的参数
      String value=this.getServletConfig.getInitParameter("data");
      //得到所有的参数
      Enumeration e=this.getServletConfig.getInitParameterNames();
      while(e.hasMoreElements()){
            String name=(String) e.nextElement();
            String value=this.getServletConfig.getInitParameter(name);
      System.out.println(name+“”+value);
      }
      *ServletConfig对象的作用
      **获得字符集编码;
      **获得数据库连接信息;
      **获得配置文件后,查看Struts案例的web.xml文件。

      6. ServletContext API

      *当web容器在启动时,它会为每一个web应用创建一个ServletContext对象,代表当前web应用。在一个web应用的所有Servlet共享同一个ServletContext对象,通常也称为Context域对象,也就是web应用作用范围。
      *ServletContext的一些方法
      **getContext()方法——返回内容
      **getResourcePaths()——返回路径
      eg:
      /welcome.html
      /catalog/index.html
      /catalog/products.html
      /catalog/offers/books.html
      /catalog/offers/music.html
      /customer/login.jsp
      /WEB-INF/web.xml
      /WEB-INF/classes/com.acme.OrderServlet.class
      
      getResourcePaths("/") 返回 {"/welcome.html", "/catalog/", "/customer/", "/WEB-INF/"}
      getResourcePaths("/catalog/") 返回{"/catalog/index.html", "/catalog/products.html", "/catalog/offers/"}.
      *ServletContext的作用
      **使用ServletContext对象来实现资源共享
      **使用Servlet的转发(与重定向的区别,对于客户机而言,发一次请求,使用重定向就发两次请求,而转发只一次)
      eg:
      RequestDispatcher rd=this.ServletContext.getRequestDispatcher("/1.jsp");
      rd.forward(request,response);//转发
      **利用ServletContext来读取资源文件——管理Servlet文件(比较重要)
      *得到文件路径
      *读取资源文件的三种方式
      *.xml文件和.properties文件(如果配置文件中的内容之间有关联,那么使用.xml文件配置相关信息,如果配置信息的内容之间不存在关联,比如连接数据库时需要使用的数据库名和数据库密码等信息,这些不存在联系,可以使用.properties文件)。
      eg:
      ******db.properties文件******
      url=jdbc:mysql://localhost:3306/test
      username=Cecilia
      password=123
      ***********Java代码*********
      public class ServletTest extends HttpServlet{
          public void doGet(HttpRequest request,HttpResponse response){
          //方法一
          testRead1();
              //方法二
          testRead2();
          }
      public void doPost(HttpRequest request,HttpResponse response){
          doGet(request,response);
      }
      public void testRead1(){
          InputStream in=this.getServletContext().getResourceStream("/WEB-INF/classes/db.properties");
       Properties p=new Properties();
       p.load(in);//加载properties文件
      //读取文件路径、用户名、密码
        String url=p.getProperty("url");
        String username=p.getProperty("username");
        String username=p.getProperty("password");
        System.out.println(url);
        System.out.println(username);
        System.out.println(password);
      }
      //通过ServletContext的getRealPath得到资源的绝对路径,再通过传统流读取资源的文件(一般应用在需要下载资源的情况场景)
      public void testRead2(){
        String path=this.getServletContext().getRealPath("/WEB-INF/classes/db.properties")
      String filename=path.subString(path.lastIndexOf("\\")+1);
      System.out.println("当前读取的资源名称是:"+filename);
      //定义传统文件流
      FileInputStream fin=new FileInputStream(path);
       Properties p=new Properties();
       p.load(in);//加载properties文件
      //读取文件路径、用户名、密码
        String url=p.getProperty("url");
        String username=p.getProperty("username");
        String username=p.getProperty("password");
      System.out.println("当前读取的资源数据是:");
        System.out.println(url);
        System.out.println(username);
        System.out.println(password);
      }
      }
      *如何在WEB应用中的Java程序如何读取资源文件?(一般Servlet不直接操作数据库,只是通过一个Dao层去处理)
      eg:
      public class ServletTest extends HttpServlet{
          public void doGet(HttpRequest request,HttpResponse response){
          //实例化Dao对象
          UserDao dao=new UserDao();
          dao.update();
      
      }
      public void doPost(HttpRequest request,HttpResponse response){
          doGet(request,response);
      }
      **************Dao类***********
      //通过读取资源文件的程序下不是servlet只能通过类装载器读取(前提是装载入的文件不能太大,否则造成内存溢出)
      public class UserDao{
      //使用静态代码块封装使用类加载器来读取资源的代码,这样有利于代码的可维护性、可读性
      private static Properties dbconfig=new Properties();
      static{
          try{
      //得到类的装载器并将其返回一个输入流
          InputStream input=UserDao.class.getClassLoader("db.properties");
          Properties p=new Properties();
          config.load(in);//加载properties文件
      
          }catch(Exception e){
          throws new ExceptionInitialiserError(e);//抛出初始化异常
          }
      
      
      }
      //方法一:使用类装载器来读取资源
         public void update(){
          //读取文件路径、用户名、密码
          System.out.println(dbconfig.getProperty("url"));
          System.out.println(dbconfig.getProperty("username"));
          System.out.println(dbconfig.getProperty("password"));
      
      }
      //方法二:先使用类装载得到文件路径,然后通过传统文件流读取资源文件,这样能够得到更新后的资源文件数据
       public void update1(){
      //如果想要在发布之后修改配置文件并刷新后能得到修改后的数据
          InputStream path=UserDao.class.getClassLoader.getResource("db.properties").getPath();//得到资源的路径
          FileInputStream fin=new FileInputStream(path);
          Properties dbconfig=new Properties();
          dbconfig.load(fin);
          //读取文件路径、用户名、密码
          System.out.println(dbconfig.getProperty("url"));
          System.out.println(dbconfig.getProperty("username"));
          System.out.println(dbconfig.getProperty("password"));
      
      }
          public void select(){}
          public void delete(){}
      }
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

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

      抵扣说明:

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

      余额充值