JavaWeb之Servelt详解

一.Servlet是什么?

Servlet(Server Applet)是指Java语言实现的一个接口,运行在服务器端,为客户端的操作做出不同的响应,实现不同功能的一段代码。

二、Servlet 创建有三种方式

1、实现 Servlet 接口

2、继承 GenericServlet 类

3、继承 HttpServlet 方法

创建 Servlet 的第三种方法,也是我们经常用的方法。

三、接口中的方法

1.Servlet中一共有五个方法

package javax.servlet;

在这里插入图片描述

  • init 第一次请求我们编写的Serlvet时,Servlet容器调用此方法,后续不在调用,可以利用这个方法做一些初始化的工作。在调用这个方法时,Servlet容器会传递一个ServletConfig。一般会将这个ServletConfig赋给一个类级变量,以方便其他方法也可以使用这个对象。
  • service 每次用户请求service时,servlet容器都会调用这个方法,我们对请求的处理就是在这里完成的。
  • destroy 要销毁Servlet时,Servlet容器就会调用这个方法,它通常发生在卸载应用程序,或者关闭Servlet容器的时候,这里一般我们会写一些资源清理相关的代码。

Servlet中另外另个费生命周期的方法:getServletInfo和getServletConfig

  • getServletInfo 就是字面意思,返回Servlet的描述
  • getServletConfig 这个方法返回由Servlet容器传给init方法的ServletConfig,上面说了,一般在init方法中将ServletConfig赋给一个类级变量,免得本方法返回null。

四、配置Servlet的方式

  1. 在web.xml配置Servlet程序,配置Servlet虚拟路径(用户通过这个虚拟路径访问Servlet程序)
	<servlet>
   		 <!-- 为 Servlet程序  命名 -->
        <servlet-name>user</servlet-name>
   		 <!-- Servlet全路径 : 包名.类名 -->
        <servlet-class>com.xinzhi.controller.UserServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- 为Servlet程序 指定 浏览器访问 虚拟路径 -->
        <servlet-name>user</servlet-name>
        <!-- 用户 在 浏览器通过/user 访问Servlet -->
        <url-pattern>/user</url-pattern>
    </servlet-mapping>
  1. 可以使用注解的方式进行Servlet配置
@WebServlet("/user")

**eg:**这两种方式不能同时使用,即配置了web.xml就不能使用注解,使用了注解就不能使用web.xml配置。

五、Servlet 加载时机

1、创建Servlet对象的时机:

默认情况下,在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有则创建它,然后根据客户的请求创建HttpRequest、HttpResponse对象,从而调用Servlet对象的service方法;

Servlet容器启动时:当web.xml文件中如果元素中指定了子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象;

<servlet>
        <servlet-name>user</servlet-name>
        <servlet-class>com.xinzhi.controller.UserServlet</servlet-class>
        <!-- 设置的数值大于0即可 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

2、Servlet对象的生命周期:

在Servlet接口中定义了5个方法,其中3个方法代表了Servlet的生命周期:

1. init(ServletConfig)方法:负责初始化Servlet对象,在Servlet的生命周期中,该方法执行一次;

2. service(ServletRequest req,ServletResponse res)方法:负责处理客户端的请求;为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性;

3. destroy()方法:当Servlet对象退出生命周期时,负责释放占用的资源;

在调用Servlet对象的destroy()方法后,Servlet由JVM的垃圾回收期进行垃圾回收。

六、Servlet匹配规则

上面的配置信息,其中标签首先配置声明一个servlet,包括servlet的名字和对应的java类名。
其中标签声明了与该servlet相应的匹配规则,每个标签代表1个匹配规则。

    <servlet-mapping>
        <!-- 为Servlet程序 指定 浏览器访问 虚拟路径 -->
        <servlet-name>user</servlet-name>
        <!-- 用户 在 浏览器通过/user 访问Servlet -->
        <url-pattern>/user</url-pattern>
    </servlet-mapping>

1、匹配规则

6.1 精确匹配

中配置的项必须与url完全精确匹配。

如配置信息如下:

    <servlet-mapping>
        <!-- 为Servlet程序 指定 浏览器访问 虚拟路径 -->
        <servlet-name>user</servlet-name>
        <!-- 用户 在 浏览器通过/user.do 访问Servlet -->
        <url-pattern>/user.do</url-pattern>
    </servlet-mapping>

当在浏览器中输入如下几种url时,都会被匹配到该servlet
http://localhost:8080/fristweb_war_exploded/user.do

6.2 扩展名匹配

如果匹配规则如下

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping></pre>

则任何扩展名为jsp(文件名和路径任意)的url请求都会匹配,比如下面的url都会被匹配
http://localhost:8080/fristweb_war_exploded/demo.do

6.3 路径匹配

路径匹配和扩展名匹配不能同时使用

使用扩展名匹配,前面就不能有任何的路径

如果匹配规则如下

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/user/*</url-pattern>
</servlet-mapping></pre>

则请求的ulr只要前面(myapp之后)的路径是/user,而后面的路径可以任意。比如下面的url都会被匹配。

http://localhost:8080/fristweb_war_exploded/user/demo.html
http://localhost:8080/fristweb_war_exploded/user/test.jsp

6.4 缺省匹配

如果配置成如下两种的任意一种

<url-pattern>/</url-pattern>

<url-pattern>/*</url-pattern>

则所有的url都可以被匹配上。其中/*是路径匹配,只是路径就是/。

2、优先顺序

路径匹配和扩展名匹配不能同时使用

当一个url与多个servlet的匹配规则可以匹配时,则按照 “ 精确路径 > 最长路径>扩展名”这样的优先级匹配到对应的servlet。举例如下:

**例1:*比如servletA 的url-pattern为 /test,servletB的url-pattern为 / ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,不会去管servletB。

**例2:**比如servletA的url-pattern为/test/,而servletB的url-pattern为/test/a/,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。

例3: 比如servletA的url-pattern:.action ,servletB的url-pattern为 / ,这个时候,如果我访问的url为http://localhost/test.action,这个时候容器就会优先进行路径匹配,而不是去匹配扩展名,这样就去调用servletB。

七、Response

response对象包含了所有从服务端返回给客户端的信息。在HTTP协议下,这些信息通过HTTP头部或者response的消息体从服务器被传输到客户端。

1. response操作响应行

在http响应行中,包括协议,版本号,以及有一个很重要的值,它叫做响应状态码.响应行中我们主要就是操作这些状态码,它可以有五种类型取值:

img

  • 常用状态码

     200请求成功(其后是对GET和POST请求的应答文档。)
     302所请求的页面已经临时转移至新的url。
     304未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
     404没有找到文件或目录。
     405请求中指定的方法不被允许
     500请求未完成。服务器遇到不可预知的情况
    
  • HttpServletResponse操作状态码API
    void setStatus(int sc,String sm) 设置状态代码
    void sendError(int sc) throws IOException设置错误状态码
    void sendError(int sc,String msg) throws IOException设置错误状态码及信息

2. response操作响应头

http响应头的格式是 name:value的格式,如果有多个value值,以”,”分开,
例如:
Content-Encoding: gzip
Content-Length: 123
Content-Language: zh-cn
Content-Type: text/html; charset=GB2312
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT

  • HttpServletResponse操作响应头 API

    public void setHeader(String name,String value)
    用给定名称和值设置响应头。如果已经设置了头,则新值将重写以前的值

    public void addHeader(String name, String value)
    用给定名称和值添加响应头。此方法允许响应头有多个值

    public void setIntHeader(String name, int value)
    用给定名称和整数值设置响应头。如果已经设置了头,则新值将重写以前的值。

    public void addIntHeader(String name, int value)
    用给定名称和整数值添加响应头。此方法允许响应头有多个值。

    public void setDateHeader(String name, long date)
    用给定名称和日期值设置响应头。该日期根据距历元时间的毫秒数指定。如果已经设置了头,则新值将重写以前的值。

    public void addDateHeader(String name, long date)
    用给定名称和日期值添加响应头。该日期根据距历元时间的毫秒数指定。此方法允许响应头有多个值。

案例1:重定向

img

实现:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	//设置状态码
        resp.setStatus(302);
        //设置响应头
        resp.setHeader("location","http://www.baidu.com");
    }

开发中我们使用sendRedirect(url);

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("http://www.baidu.com");
    }

案例2:定时跳转

在servlet中,我们通过

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(302);
        resp.setHeader("refresh","3,http://www.baidu.com");
    }

在页面中,我们可以通过
<meta http-equiv="refresh" content="5;url=http://localhost/day09/responseDemo3">
页面中通过方式操作时,也会将标签内容写入到http响应中。

重定向是两次请求;

重定向的URL可以是其他应用,不局限于当前应用;

重定向的响应头是302,并且必须要有Location响应头;

八、Request

HttpServletRequest对象用于封装http请求,对于http请求它有三部分组成,http请求行,http请求行及请求正文。

1. request操作请求行

public String getMethod()
返回用于发出此请求的 HTTP 方法的名称,例如 GET、POST
public String getRequestURI()
返回此请求的 URL 的一部分,从协议名称一直到 HTTP 请求的第一行中的查询字符串。
public String getProtocol()
以 protocol/majorVersion.minorVersion 的形式(例如 HTTP/1.1)返回请求使用的协议的名称和版本。
public String getQueryString()
返回包含在请求 URL 中路径后面的查询字符串。如果 URL 没有查询字符串,则此方法返回 null。

2. request获取客户信息

public String getContextPath()
返回请求 URI 指示请求上下文的那一部分。
public StringBuffer getRequestURL()
重新构造客户端用于发出请求的 URL。返回的 URL 包含一个协议、服务器名称、端口号、服务器路径,但是不包含查询字符串参数。
public String getRemoteAddr()
返回发送请求的客户端或最后一个代理的 Internet Protocol (IP) 地址

3. request操作请求头

public String getHeader(String name)
以 String 的形式返回指定请求头的值。
public java.util.Enumeration<E> getHeaders(String name)
以 String 对象的 Enumeration 的形式返回指定请求头的所有值。
public java.util.Enumeration<E> getHeaderNames()
返回此请求包含的所有头名称的枚举。如果该请求没有头,则此方法返回一个空枚举。
public int getIntHeader(String name)
以 int 的形式返回指定请求头的值。如果该请求没有指定名称的头,则此方法返回 -1。如果无法将头转换为整数,则此方法抛出 NumberFormatException。
public long getDateHeader(String name)
以表示 Date 对象的 long 值的形式返回指定请求头的值

**4. request获取请求参数

请求参数是浏览器发送请求时携带的信息。
对于请求方式GET与POST,请求参数存在位置不同。
GET:请求参数存在于请求的资源路径中。
POST:请求参数存在于正文中

public String getParameter(String name)
以 String 形式返回请求参数的值,如果该参数不存在,则返回 null
public String[] getParameterValues(String name)
返回包含给定请求参数拥有的所有值的 String 对象数组,如果该参数不存在,则返回 null。
public java.util.Map<K, V> getParameterMap()
返回此请求的参数的 java.util.Map。请求参数是与请求一起发送的额外信息。对于 HTTP servlet,参数包含在查询字符串或发送的表单数据中。
public java.util.Enumeration<E> getParameterNames()
返回包含此请求中所包含参数的名称的 String 对象的 Enumeration。如果该请求没有参数,则此方法返回一个空的 Enumeration。

**5. request域对象的介绍

request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理.

 setAttribute方法
 getAttribute方法
 removeAttribute方法
 getAttributeNames方法

request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发,从而共享请求中的数据

**6. 请求转发

请求转发可以实现路径的跳转操作.
ReqeustDispatcher dispatcher=request.getRequestDispatcher("路径")
dispatcher.forward(request,response)

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = new User(1,"zhangsan","12");
        req.setAttribute("user",user);
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/user.do");
        requestDispatcher.forward(req,resp);
    }

请求转发和重定向的区别:

1.请求转发是服务器内部跳转,地址栏不会发生改变
重定向地址栏会发生改变。

2.请求转发,只有一次请求,一次响应.
重定向,有两次请求,两次响应。

3.请求转发存在request域,可以共享数据.
重定向不存在request域。

4.请求转发只能在服务器的内部跳转,简单说,只能访问本站内资源。
重定向可以访问站外资源,也可以访问站内资源.

5.请求转发是由request 发起的 . request.getRequestDispatcher().forward()
重定向是由response 发起的 response.sendRedirect();

6.请求转发与重定向时路径写法不一样.
重定向要跳转的路径是从浏览器在次发起的,是浏览器端路径,写法: /工程名/资源
请求转发是服务器内部跳转,这时它与浏览器无关 写法:/资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值