现在的位置: 首页 > 综合 > 正文

第六天:Servlet入门

2018年05月17日 ⁄ 综合 ⁄ 共 9047字 ⁄ 字号 评论关闭

l 一个Servlet程序就是一个实现了特殊接口的Java类,它由支持Servlet(具有Servlet引擎)的WEB服务器调用和启动运行。Web服务器可以把一个或一组URL地址的访问请求交给某个的Servlet程序去处理,Servlet可以接收到客户端的请求信息和产生响应内容。

lWEB-INF下的文件是无法访问的。是一个私有目录无法通过浏览器访问。所以把libclass,web.xml这三个东西,放在这下面,因为这三个完全不需要用户访问,并且是高度保密的,这三个东西是让tomcat看的。所以它会把其它要用户要访问的放在外面。

 

用户一旦访问网站tomcat会把class目录下的字节码文件在tomcat里面运行,然后把结果通过tomcat返回给用户,这是过程。

 

http://localhost:8888/day06_servlet_01/xxx.html?username=23

 

寻找servlet jar

 

部署前,对着tomcat自带的例子应用说清楚javaweb应用程序的目录结构(并画一个图关系结构图),然后解释开发环境和运行环境的区别,说清楚MyEclipse是如何发布web应用的,通过修改web虚拟目录的名字来强调。

最后按照后面的ppt总结下用手工方式如何做,因为面试时要试探你的工作是真的明白,还是照猫画虎,就会考这个问题。

 

myelclipse里面找web可以修改虚拟路径。

 

我们发布的是什么呢,就是在开发环境中把WebRoot下的所有文件文件到搬到tomcat里面去。如果是静态页面直接就搬过去,如果是java要部署后才能发搬过去。

 

 

同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。

同一个Servlet类可以被注册多次,即创建出这个Servlet类的多个实例对象。

Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。带扩展名的*前不能有“/”,即不能设置为“/action/*.xx”形式。

如果没有通配符,那么url-pattern必须以/开头。十分重要!

 

<servlet>

       <servlet-name>dog</servlet-name>

       <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>

    </servlet>

    同一个Servlet类可以被注册多次,即创建出这个Servlet类的多个实例对象

    <servlet>

       <servlet-name>cat</servlet-name>

       <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>

    </servlet>

   

    同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名

   

    <servlet-mapping>

       <servlet-name>dog</servlet-name>

       <url-pattern>/xxx.html</url-pattern>

       <url-pattern>/yyy.html</url-pattern>

    </servlet-mapping>

   

    <servlet-mapping>

       <servlet-name>cat</servlet-name>

       <url-pattern>/abc.html</url-pattern>

       <url-pattern>/yt.html</url-pattern>

</servlet-mapping>

 

 

对于如下的一些映射关系:

/abc/*  映射到 
Servlet1

/*      映射到 
Servlet2

/abc    映射到 
Servlet3

*.do    映射到 
Servlet4

将发生如下一些行为:

当请求URL为“/abc/a.html”,“/abc/*”和“/*”都可以匹配这个URL

Servlet引擎将调用Servlet1

当请求URL为“/abc”时,“/abc/*”和“/abc都可以匹配这个URL

Servlet引擎将调用Servlet3

当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都可以匹配这个URL

Servlet引擎将调用Servlet1

当请求URL为“/a.do”时,“/*”和“*.do”都可以匹配这个URL

Servlet引擎将调用Servlet2

当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都可以匹配这个URL

Servlet引擎将调用Servlet2

 

 

Servlet的运行过程:

①   Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。

②   装载并创建该Servlet的一个实例对象。

③   调用Servlet实例对象的init()方法。

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

⑤   WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servletdestroy()方法。

 

 

Servlet程序查询数据库的工作过程:

 

 

 

Servlet的运行过程à特殊说明:

<servlet>元素中嵌套一个<load-on-startup>子元素,WEB应用程序在启动时就可以装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

举例:

<servlet>

      <servlet-name>invoker</servlet-name>

      <servlet-class>

            org.apache.catalina.servlets.InvokerServlet

      </servlet-class>

      <load-on-startup>2</load-on-startup>

</servlet>

Servlet的整个生命周期内,它的init方法只被调用一次,而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servletservice方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servletservice()方法。

Tomcat也提供了是否自动重新装载被修改的Servlet的配置选项。在<Tomcat安装主目录>/conf/server.xml文件中,可以将<Context>元素的reloadable属性设置为true,这样,Tomcat将监视该WEB应用程序的/WEB-INF/classes/WEB-INF/lib目录下的类是否发生了改变,然后自动重新装载那些发生了改变的类。

举例:

<Context path="/it315"docBase="d:\myweb" debug="0"reloadable="true"/>

 

其实有更为简单的方法:只对本程序起作用,在META-INF下。建立一个Context.xml文件。

<Context
reloadable="true">

</Context>

 

Servlet API就是接口,只是在开发编译的时间需要这个接口编译成功,然后在运行的时间具体的实现类是在容器中的。这才是它们之间的重要关系,

就像request的具体实现类是org.apache.catalina.connector.RequestFacade在我们开发的包中里面根本没有,只是在容器中调用的时间才有的。我们开发用的环境和API中没有,只有它父类的一个接口,只要保证编译成功就行。

 

Servlet是一个并不是一个单例,如果一个servlet映射一个文件,那么是单例,如果不是那么就不是。

<load-on-startup>1</load-on-startup>  是指,没有它,就是在用户第一次访问时间调用 init方法,如果加上了就是在服务器启动过程中就调用了(先是构造方法,再是init)。

如果没有就是等到第一次调用时间。

 

 

ServletConfig:可以得到servlet的配置信息,非常好。

Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以,Serlvet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称和初始化参数等信息也需要传递给该Servlet

 

 

listings            Shoulddirectory listings be produced if there -->

  <!--                       is no welcome file in this directory? 
[false] -->

  <!--                       WARNING: Listings fordirectories with many    -->

  <!--                       entries can be slow andmay consume     

也就是说如果没有找到那个文件是进行404还是进行目录列表。

 

 

 

 

//在这里写成GBKUTF-8都行,只要是汉字编码,因为这样服务器才会把这些字符以中文的编码送出去。这个东西有两个方面的作用,第一个,告诉以什么的编码传过去,第二、告诉浏览器我是什么编码,让浏览器用相应的东西解码。

       response.setContentType("text/html;charset=GBK");

    response.getWriter().println(config.getInitParameter("Corporation")+"欢迎你");

 

 

    Enumeration<String> enumeration =
config.getInitParameterNames();

       while (enumeration.hasMoreElements()) {

           String param = (String) enumeration.nextElement();

           String value =
config
.getInitParameter(param);

           response.getWriter().println("param:"+param+"   
"+"value:"+value);

    }

 

ServletCofig四个方法:

getInitParameterNames

getInitParameter

getServletName

getServletContext

 

ServletContext(Servlet的环境):它的范围就是一个webapp,一个webapp只有一个ServletContext.你就把它看成jsp中的application就行了。

 

      servletServletContext的关系时,画图说明一个站点(一个Tomcat服务器,也即Servlet容器)下有多个ServletContext(一个ServletContext就是一个Web应用程序),每个ServletContext下又有多个Servlet,可以认为ServletContext对象就是Servlet的环境。

 

Servlet引擎为每个WEB应用程序都创建一个对应的ServletContext对象,ServletContext对象被包含在ServletConfig对象中,调用ServletConfig.getServletContext方法可以返回ServletContext对象的引用。

由于一个WEB应用程序中的所有Servlet都共享同一个ServletContext对象,所以,ServletContext对象被称之为application
对象(Web应用程序对象)。 

 

ServletContext可以通过ServletConfig获得,ServletContext的应用:

可以得到这个webapp的真实路径(getRealPath),还可以从webapp中读取某个文件

以流的形式(getResourceAsStream)。

 

程序中相对路径都是相对于当前工作目录。在tomcat里面就是指那个tomcat下面的

Bin目录下,因为服务器在这里启动。

ServletContext接口

功能:

ü  获取WEB应用程序的初始化参数

ü  记录日志

ü  application域范围的属性

ü  访问资源文件,牢牢记住三种访问方式:classpathwebappFileSystem打死你也不要用相对路径)。

ü  获取虚拟路径所映射的本地路径

ü  WEB应用程序之间的访问

ServletContext的其他方法

       十分重要:(要会默写)

       ServletContext application =
config.getServletContext();

//     getRealPath(java.lang.Stringpath)

//        Returns a String containing the realpath for a given virtual path.

       String realpath = application.getRealPath("/WEB-INF/downloads");

       File download = new File(realpath);

       if (!download.exists()) {

           download.mkdir();

       }

      

       String fileName = request.getParameter("filename");

       FileOutputStream out =
new
FileOutputStream(realpath+"/"+fileName);

       out.close();

 

你直接写个newFileoutputStream(“db.properties”)它是到tomcatbinhhiv gh
去找这个文件,这就是相对路径的坏处,在哪里面执行的,就去哪里找。

 

访问资源文件,牢牢记住三种访问方式:

classpath、(是类加载器目录,在src目录下)

webapp、(在web应用中读取/WEB-INF/c.txt

FileSystem(d:/32.txt).

 

只有这有三种,且记。

 

我们要知道,不能把我们配置文件放在项目的根目录下面,因为这样用户可以通过浏览器访问,之所以要出现WEB-INF这个私密目录,就是为了让程序访问,而用户不能够访问,所以可以把它放在这下面,通过获得真实路径的filesystem方法访问和通过ServletContext访问。

当然也可以在src目录下面,通过类加载器的方法访问。

 

 

 

    //访问文件的三种方式(

       //第一种:通过获得真实路径是访问的文件系统

       String dbRealpath = application.getRealPath("/WEB-INF/db.properties");

       System.out.println(dbRealpath);

       InputStream inputStream =
new FileInputStream(dbRealpath);

       Properties properties =
new
Properties();

//     properties.load(inputStream);

//     properties.list(response.getWriter());

      

       //第二种是通过webapp来访问的

      

//     properties.load(

//            application.getResourceAsStream("/WEB-INF/db.properties")

//     );

//     properties.list(response.getWriter());

      

       //第三种是通过classpath访问的,要把它放在src目录下。就是在运行的环境的classes目录下。

      

       properties.load(

              FirstServlet.class.getResourceAsStream("/db.properties")

       );

       properties.list(response.getWriter());

 

 

ServeletContext. getResourceAsStream()这个方法与我们所说的类加载器的getResourceAsStream方法是不同的,类加载器中我们只能访问src目录下的东东,然后这个

ServletContext却可以访问webapp中任何地方的资源 ,包括WEB-INF。

This method isdifferent from java.lang.Class.getResourceAsStream, which uses aclass loader. This method allows servlet containers to make a resource availableto a servlet from any location, without using a class loader.

我们所说的WEB-INF是不能被用户通过浏览器直接访问,而可以被应用程序本身访问。

 

 

ServletContext获取WEB应用程序的初始化参数

ServletConfig中获得初始化参数:

<servlet>

       <servlet-name>dog</servlet-name>

       <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>

       <init-param>

           <param-name>Corporation</param-name>

           <param-value>北京传智播客公司</param-value>

       </init-param>

       <init-param>

           <param-name>site</param-name>

           <param-value>itcast.cn</param-value>

       </init-param>

      

    </servlet>

只有在说这个servlet被访问时间才能访问到它的初始化变量。

 

但是我们想要全局访问,任何一个serlvet都想访问,怎么办?就是用设置一个全局的初始化参数,然后用全局的ServletContext访问。

web.xml里面写上:

    <context-param>

       <param-name>debug</param-name>

       <param-value>true</param-value>

    </context-param>

你可能平常不用,但是在spring里面有大量这样的配置,要看得懂。

//获得全局初始化参数

       String
debug
= application.getInitParameter("debug");

       response.getWriter().println(debug);

 

HttpServlet:

public abstract class HttpServlet

extends GenericServlet

 

public abstract class GenericServlet

extends java.lang.Object

implements Servlet,ServletConfig,java.io.Serializable

GenericServlet里面封装了getServletConfig()getServletContext()方法,

service(ServletRequest req,
ServletResponse res)

          Called by theservlet container to allow the servlet to respond to a request.

两个方面,以后在HttpServlet可以直接用上面两个方法,获得config
ServletContext太有用了,对吧。但是这个里面的Service方法,的参数类型

不太好,如果是HttpServletRequest就好了,

那么我们在HttpServlet方法中实现了两者的完美结合:

service(HttpServletRequest req,HttpServletResponse resp)

不但不用再转型 ,而可以直接通过上面两个get方法获得想要的东东。      

 

 

抱歉!评论已关闭.