Servlet

 一、简介

  接收请求、处理请求、完成响应

二、创建HelloServlet  

a) 创建动态WEB项目WEB_Servlet

b) 项目下创建包com.atguigu.web.servlet

c) 包下创建一个类HelloServlet实现javax.servlet.Servlet接口

d) 在HelloServletservice()方法加入一行打印语句System.out.println(“hello”);

e) 在WEB-INF目录下的web.xml文件中注册映射Servlet

f) 启动服务器,在浏览器中访问http://localhost:8080/WEB_Servlet/HelloServlet

三、Servlet生命周期

  Servlet的生命周期指的是Servlet由实例化到被销毁的过程同样也被分为三个阶段:实例化、处理请求、被销毁。而每个阶段我们都有对应的方法来实现响应的功能,在实例化阶段需要调用init()方法来做初始化操作处理请求阶段调用service()方法处理请求,销毁对象之前调用destroy()释放资源等操作。

四、Servlet相关接口

  ServletRequest和ServletResponse

    ServletRequest由容器创建并传递到service()方法中,容器所创建的对象实际上是HttpServletRequest,所以开发中我们都会将ServletRequest强转HttpServletRequest。

  HttpServletRequest方法

    String getParameter(String paramName):获取指定请求参数的值;

    String getMethod():获取请求方法,例如GETPOST

    String getHeader(String name):获取指定请求头的值;

    void setCharacterEncoding(String encoding):设置请求体的编码!因为GET请求没有请求体,所以这个方法只只对POST请求有效。当调用request.setCharacterEncoding(“utf-8”)之后,再通过getParameter()方法获取参数值时,那么参数值都已经通过了转码,即转换成了UTF-8编码。所以,这个方法必须在调用getParameter()方法之前调用!

  HttpServletResponse的方法

    PrintWriter getWriter():获取字符响应流,使用该流可以向客户端输出响应信息。例如response.getWriter().print(“<h1>Hello JavaWeb!</h1>”)

    ServletOutputStream getOutputStream():获取字节响应流,当需要向客户端响应字节数据时,需要使用这个流,例如要向客户端响应图片;

    void setCharacterEncoding(String encoding):用来设置字符响应流的编码,例如在调用setCharacterEncoding(“utf-8”);之后,再response.getWriter()获取字符响应流对象,这时的响应流的编码为utf-8,使用response.getWriter()输出的中文都会转换成utf-8编码后发送给客户端;

    void setHeader(String name, String value):向客户端添加响应头信息,例如setHeader(“Refresh”, “3;url=http://www.atguigu.com”),表示3秒后自动刷新到http:// www.atguigu.com;

    void setContentType(String contentType):该方法是setHeader(“content-type”, “xxx”)的简便方法,即用来添加名为content-type响应头的方法。content-type响应头用来设置响应数据的MIME类型,例如要向客户端响应jpg的图片,那么可以setContentType(“image/jepg”),如果响应数据为文本类型,那么还要台同时设置编码,例如

setContentType(“text/html;chartset=utf-8”)表示响应数据类型为文本类型中的html类型,并且该方法会调用setCharacterEncoding(“utf-8”)方法;

  void sendError(int code, String errorMsg):向客户端发送状态码,以及错误消息。例如给客户端发送404response(404, “您要查找的资源不存在!”)

  ServletConfig

    ServletConfig对象对应web.xml文件中的一个<servlet>元素,例如:想要获取元素中的<servlet-name>那么可以使用servletConfig.getServletName()方法来获取。

    ServletConfig对象同样有容器创建,然后作为参数传递init()方法,可以在init()方法中使用。

  ServletConfig的方法:

    String getServletName():获取Servletweb.xml文件中的配置名称,即<servlet-name>指定的名称;

    ServletContext getServletContext():用来获取ServletContext对象,ServletContext会在后面讲解;

    String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;

    Enumeration getInitParameterNames():用来获取在web.xml中配置的所有初始化参数名称;

    在web.xml中servlet配置初始化参数

<servlet>

<servlet-name>HelloServlet</servlet-name>

<servlet-class>省略</servlet-class>

<init-param>

<param-name>username</param-name>

<param-value>root</param-value>

</init-param>

</servlet>

    每一个init-param表示一个初始化参数,通过getInitParameter(String name)可以根据param-name的值获取到param-value值。

    每个servlet中可以配置多个init-paramservlet只能获取自身的初始化参数,而不能获得其他servlet的初始化参数。

五、 GenericServlet

 

  在显示开发中我们如果直接实现servlet接口功能也是可以正常实现的,但是所面临的问题是如果我直接实现Servlet接口,那接口中的所有方法都必须要实现,但是这些方法有的我们用不到,而有的方法实现起来很麻烦而且没给servlet实现的代码都差不多于是我们就需要一个抽象类来帮助我们实现servlet接口,实现一些通用的方法,而我们只需要继承GenericServlet就可以了,这样的好处是我们不在需要重写全部方法而只需要重写必须的和我们需要的方法就可以

六、HttpServlet

  HttpServletGenericServlet子类,他是Tomcat中专门处理HttpServlet的Servlet(实际Tomcat只处理Http类型的请求)所以在一般情况下我们都会通过继承HttpServlet来实现servlet

  HttpServletGenericServlet一样都是一个抽象类,也就是不能对它们进行实例化,与GenericServlet不同HttpServlet没有任何抽象方法,所以需要我们根据实际需求来重写它的方法。

  在GenericServletservice(ServletRequest req, ServletResponse res)方法是一个抽象方法,必须要由子类实现,而在HttpServlet中已经被实现,HttpServlet实现的方法中会被强制转换成HttpServletRequestHttpServletResponse(不用担心会出现类型转换异常,因为传过来的对象本身就是该类型)转换类型之后会调用HttpServlet中的一个重载的service(HttpServletRequest req, HttpServletResponse resp)方法也就是说如果我们要重写service()方法不必再去重写GenericServletservice()方法了,而可以直接重写HttpServlet重载的service()方法就可以了。

  在service(HttpServletRequest req, HttpServletResponse resp)方法它的请求类型进行判断,然后根据请求类型的不同再去调用不同的方法:post类型的请求回去调用doPost()get请求回去调用doGet()delete请求回去调用doDelete(),以此类推。但是实际应用中我们只会使用到doPost()和doGet(),所以一般情况下我们不会去重写service()方法而是去重写更简单的doGet()或者doPost()。

七、关于servlet提问:

  1、Servlet的构造器调用了几次?

    Servlet是单实例,而调用构造器就是用来创建实例的,所以只调用一次。

  2、Servlet线程安全的吗?

    由于Servlet是单实例的,所以当容器调用service方法处理请求时以多线程的方式调用的,但是因为性能问题所以在这方法中并没有考虑同步的问题,所以Servlet并不是线程安全的,但是这样做的好处是性能较好。由于Servlet不是线程安全的,所以尽量不要在使用Servlet处理请求时操作变量,因为有可能会出现同步的问题。(实际应用中只有非常高的并发的情况下有可能出现这个问题,虽然如此但还是尽量不要那么做)。

  3、Servlet实例只能在第一次请求时被创建吗?

    一般情况Servlet会在第一次收到请求时被创建,所以当我们第一次访问某个Servlet时平时慢一些这种我们称为第一次惩罚。

    如果希望在服务器启动时就创建Servlet的实例可以在web.xml进行配置,在servlet标签中还有一个load-on-startup标签,这个标签需要一个大于等于0的整数作为参数,当配置了这个属性后,该Servlet将会在服务器启动时就被创建,且值越小创建的时机越早。

  4、url-pattern映射的规则是什么?

 

    url-pattern配置Servlet映射的地址,他的配置规则如下:

 

    精确匹配

 

      当前项目指定URL必须完全

 

      如:/path/ServletName

 

      只有URLhttp://localhost:8080/项目名/path/ServletName

 

      由此也可知/代表的项目根目录而在html/代表的是服务器根目录

 

    路径匹配:

 

      当前项目指定路径URL地址

 

      如:/path/*

 

      当URL为:http://localhost:8080/项目名/path/任意值

 

    全匹配:

 

      当前项目所有的URL地址

 

      如:/*

 

      所有URL可以

 

    后缀匹配

 

      当前项目指定后缀的URL地址

 

      如*.action

 

      当URL为http://localhost:8080/项目名/任意值. action 

优先级:

1、精确匹配

2、路径匹配

3、全匹配

4、后缀匹配

5、还有一种“/”,这种也是全部匹配,优先级最低

 

 

关于*”:

 

*”就是通配符匹配任意字符

 

*”只能出现前面和后面,不能出现在中间

 

如:/*.action错误

 

*”只能出现一次

 

如:*/*错误

 

*”不能单独出现

 

如:* 错误

5、web.xml文件仅仅是看到的那么简单吗?

    web.xml文件整个项目中的配置文件,非常重要。但是纵观我们项目下的web.xml文件似乎内容不多,那如此重要的文件为什么只配置的这么少的内容呢?实际上在Tomcat还有一个总的web.xml文件,就在%CATALINA_HOME%/conf目录。(session过期时间啥的)

         未完待续……

      

原文地址:https://www.cnblogs.com/12344321hh/p/8661922.html