四:Day02_JavaEE:Servlet02

一、Servlet的使用

  1. update resources:变更了资源,表示当修改了静态资源,比如HTML、css等,可以使用资源变更。

  2. update classes and resources:对类的修改使用不生效,所以不建议使用。

  3. Redeploy:重部署,这个适合于修改了代码,可以重新部署项目到服务器,修改了web.xml重部署不生效。(修改了静态资源和类)

  4. restart server:重启服务器,修改了代码,web.xml,重启服务器。

2. IDEA集成Tomcat服务器项目部署介绍

Idea中编写了Servlet,并成功访问后,Tomcat的webapps目录中并没有部署当前访问的项目。

项目部署到了idea保存项目的文件夹中。赋值了Tomcat必要文件,并会指定Tomcat到指定的目录中加载项目。

好处:每个项目单独管理,单独配置,不相互影响。

二. web.xml配置Servlet的几种方式

1. 介绍

通过web.xml配置了Servlet所在类的全路径,配置了访问Servlet的映射路径。

在服务器启动的时候完成web.xml文件的加载。

2. 配置方式

  
    <servlet>

        <!--
            servlet-name:配置Servlet在容器中的一个代号,可以随便写。一般写成类名即可
            servlet-class:配置你的Servlet所在的全路径名字
        -->
        <servlet-name>a</servlet-name>
        <servlet-class>com.lyx.Servlet.Servlet</servlet-class>
    </servlet>

    <servlet-mapping>
    <!--
      servlet-name:这里的名字一定要和上面配置的servlet-name 一样!!!
       url-pattern:配置url的映射路径,也就是你的这个Servlet需要浏览器通过什么请求路径访问你
                   浏览器路径需要这样写:http://ip地址:端口号/项目名/你的url-pattern
        -->
        <servlet-name>a</servlet-name>
        <url-pattern>/a</url-pattern>


  <!--
    说明:一个Servlet可以配置多个url-pattern,但是多个Servlet不能配置相同的url-pattern,
            这样的话请求过来后tomcat不知道该调用哪个Servlet进行处理
  -->

      <!--  精确匹配的优先级高于通配符匹配的-->
        <!--方式一:/内容
        访问时必须严格匹配-->
        <url-pattern>/first</url-pattern>
        <url-pattern>/user/first</url-pattern>
       <!-- 方式二:/内容.do
           访问时必须严格匹配
       -->
     <url-pattern>/a.do</url-pattern>
      <!--  方式三:/*.do
        访问时以.do结尾就可以-->
        <url-pattern>/*.do</url-pattern>
        <!--方式四:/*
        访问时所有内容匹配-->
        <url-pattern>/*</url-pattern>
      <!--  方式五:/
        访问时除了jsp,其它全部匹配-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

3. web.xml配置欢迎页面

一般在我们项目中要设置默认欢迎页的话,在自己项目的web.xml中设置即可。不要改Tomcat中的conf/web.xml进行设置。

<welcome-file-list>
    <welcome-file>hello.html</welcome-file>
</welcome-file-list>

三、Servlet的继承结构

1. 继承结构体系

  • tomcat服务器提供了Servlet规范的实现。编写的代码想被服务器调用,必须遵守Servlet规范。

  • 自定义的Servlet类并没有去直接实现Servlet接口,是因为该接口中方法较多,Servlet接口有它的一系列实现类,代码继承实现类即间接的实现了Servlet接口。1.编写

HelloServlet为自己编写的Servlet类继承了HttpSsevlet类。

2. 相关类介绍

2.1 Servlet接口
init()创建Servlet对象后立即调用该方法完成一些初始化工作。
service()处理客户端请求,执行业务操作,可以利用响应对象响应客户端请求。
destroy()在销毁Servlet对象之前调用该方法。
getServletConfig()ServletConfig是容器向servlet传递参数的载体。
getServletInfo()获取servlet相关信息。

2.2 ServletConfig接口
String getServletName()返回 Servlet 的名字,即 web.xml 中 <servlet-name>元素的值。
ServletContext getServletContext()返回一个代表当前 Web 应用的 ServletContext 对象。
String getInitParameter(String name)根据初始化参数名返回对应的初始化参数值。
Enumeration getInitParameterNames()返回一个 Enumeration 对象,其中包含了所有的初始化参数名。
2.3 GenericServle抽象类

GenericServlet是实现了Servlet接口的抽象类。在GenericServlet中进一步的定义了Servlet接口的具体实现,其设计的目的是为了和应用层协议解耦,在GenericServlet中包含一个Service抽象方法。

2.4 HttpServlet类
  • 继承自 GenericServlet,针对于处理 HTTP 协议的请求所定制。
  • 在 HttpServlet的service() 方法中已经把 ServletReuqest  和  ServletResponse  转为 HttpServletRequest 和 HttpServletResponse。
  • 直接使用 HttpServletRequest 和 HttpServletResponse, 不再需要强转。实际开发中, 直接继承 HttpServlet, 并根据请求方式复写相应方法即可。

3.总结和注意事项

注意事项: 

tomcat服务器在接收到浏览器的请求后,会调用Servlet的service方法处理器请求,如果当前自定义的Servlet类没有service方法会调用父类的service方法进行处理。

四、Servlet的生命周期

1. 执行过程

Servlet的生命周期是由容器管理的,分别经历三各阶段:

  • init():初始化,创建完servlet对象的时候调用。只调用1次。

构造方法: 创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象 只调用1次。证明servlet对象在tomcat是单实例的。

通过映射找到到servlet-class的内容,获得 包名+类名,通过反射构造servlet对象。

  • service():执行, 每次发出请求时调用。调用n次。
  • destroy():销毁,销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。

2.使用Servlet过程

2.1 编写
public class HelloServlet extends HttpServlet {

    //构造方法就是用来创建对象的
    public HelloServlet() {
        System.out.println("构造方法被执行!!!");
    }

    //初始化方法就是做一些初始化的工作,例如:建立数据库连接池,获取配置文件信息等
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("初始化方法被执行!!!");
    }

    //service方法就是用来处理请求的
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet.service方法被执行!!!");
    }

    //销毁Servlet对象时会先执行销毁方法,可以用来释放资源。
    @Override
    public void destroy() {
        System.out.println("销毁方法被执行!!!");
    }
}
2.2 配置
<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.bjsxt.controller.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
2.3 启动和停止服务器

1.启动服务器3次的结果

2.停止服务器的结果

 2.4 load-on-startup 

配置 load-on-startup 会在启动服务器时就创建并初始化Servlet对象,  数字越小,优先级越高。 

 在web.xml中添加load-on-startup的配置

 <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.bjsxt.controller.HelloServlet</servlet-class>

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


</servlet>

<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>

3. 总结

  • 当客户端浏览器第一次请求Servlet时,容器会创建和初始化Servlet对象(只进行一次)。
  • 配置了load-on-startup启动容器时就会会创建和初始化Servlet对象(只进行一次),并在新的线程中使用Servlet对象执行service方法处理请求(进行多次)。
  • 避免使用全局变量, 多个线程操作全局变量存在线程安全的问题, service()方法中的局部变量不存在线程安全问题。
  • service方法执行完毕后容器不会销毁这个Servlet而是做缓存处理,当客户端浏览器再次请求这个Servlet时,容器会从缓存中直接找到这个Servlet对象,并再一次在新的线程中执行Service方法。当容器在销毁Servlet之前对调用一次destroy方法。

没有配置load-on-startup的情况:

配置了load-on-startup的情况:

服务器启动的时候就会执行 构造方法,然后执行初始化方法。之后有请求过来,就直接走service方法进行处理。服务器停止的时候,执行销毁方法。

五. Servlet在Tomcat中运行的原理

1.启动Tomcat服务器

(以下动作只在服务器启动的时候执行) 

1.1.解析web项目的web.xml文件:

  1. 默认的servlet

    解析web.xml,解析出url-partten和servlet-class。

  2. 配置了load-on-startup

    解析web.xml,解析出的url-partten作为key,servlet-class中的包名和类名,通过反射创建Servlet对象。将实例化的Servlet对象作为value存储在map集合中。

1.2.Tomcat服务器接收请求 :

例如:请求地址: http://localhost:8080/servlet_day02_war_exploded/aa

 1.3.Tomcat服务器解析请求,查找请求的资源:

 Tomcat服务器解析请求,查找请求的资源:

  1. 默认的servlet(在第一次访问时进行)

    根据url中解析结果,找到web.xml中匹配的url-partten,获取包名和类名,利用反射完成方法的调用。

  2. 配置了load-on-startup(在服务器启动时进行)

    根据url中解析结果,在map集合中根据key(url-partten)获取对应的实例化对象。

    Servlet servlet = map.get(key);

    servlet.service(request, reponse;

2.Servlet使用流程总结 

2.1 代码编写流程
  1. 打开IDEA

  2. 在IDEA中创建一个Java Enterprise项目

    1. 配置本机的Tomcat服务器,第一次需要配置,后续不需要再配置。

    2. 勾选Web Application,创建web引用程序,自动创建web.xml。

  3. 在项目的src目录下创建一个com.bjsxt.servlet包,在包中创建自己的类继承HttpServlet。

  4. 重写service方法或dooGet()(只能接收get请求)或doPost()(只能接收post请求),在service方法中写的就是处理请求的业务逻辑代码。

  5. 在web.xml中配置映射关系

    1. 配置servlet的访问路径。

  6. 启动tomcat服务器

    1. tomcat服务器会解析web.xml。

  7. 在浏览器输入路径访问Servlet

    1. tomcat接收到客户端的请求后,会创建请求与响应对象,调用请求的serlvet执行service方法,

      将创建的请求与响应对象以参数的形式传递到service方法中。

2.2 代码执行流程

(看不到)

  1. tomcat服务器启动时,会加载解析我们项目的web.xml文件。

  2. tomcat服务器根据解析的结果,创建所有在web.xml中配置的Servlet对象(假设都配置了load-on-startup)。

  3. tomcat服务器将所有创建好的Servlet对象以键值对的形式放在内存中,键是你配置的url-pattern,值是Servlet对象。

  4. 在浏览器地址栏输入url地址,比如:http://localhost:8080/demo/Hello

  5. tomcat服务器接收到浏览器发送的http请求,然后进行解析,得到本次请求的两个对象,HttpServletRequest和HttpServletResponse。

  6. tomcat服务器解析url地址中要访问的资源,根据资源路径找到提前创建好的Servlet对象。

  7. tomcat服务器根据反射调用Servlet对象的service方法,并将此次请求解析出的request和response对象传递给service执行。

  8. service方法执行完后,tomcat会按照http响应的格式将数据响应给浏览器。

  9. 浏览器接收到tomcat的响应结果后,对其进行解析,以网页的形式展示给用户看。

六、请求对象(HttpServletRequest)

1.get和post方法区别

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请求只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

  • GET请求在URL中传送的参数是有长度限制的,而POST则没有。对参数的数据类型GET只接受ASCII字符,

  • POST既可是字符也可是字节。

  • GET相比POST来说不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

  • GET参数通过URL传递,POST放在Request body中。

2. service方法的再次强调

2.1 service方法的作用

在service方法中编写处理请求的业务逻辑代码,浏览器发送请求后由tomcat服务器自动调用执行。

2.2 service方法的方法体

service方法中写业务逻辑代码的话,大概是如下三步:

  1. 获取请求数据

  2. 处理请求数据

  3. 处理响应

3. HttpServletRequest对象获取请求数据

request对象的来源

浏览器发送请求后,由tomcat服务器接收到,然后对请求的信息进行解析,将解析结果封装到HttpServletRequest和HttpServletResponse两个对象中。

然后tomcat通过反射调用service方法的时候,又将这两个对象传递给了service方法。

request对象的特点

  • 在tomcat服务器接收请求后,对请求进行解析后创建的。

  • 每次请求,tomcat服务器都会重新创建request 。

  • request对象存储了此次请求的所有数据(http协议中的请求行、头、体)。

request对象的使用

  • request对象获取请求行数据

  • request对象获取请求头数据

  • request对象获取请求体数据

  • request对象获取其他数据

4. 请求数据乱码问题解决

目前我们在请求体中如果携带的请求数据存在中文,在后台使用req.getParameter方法获取的时候会出现乱码,出现乱码的本质原因是因为编码与解码方式不一致导致的。

Tomcat服务器接收到请求后,会解析请求,并将请求中的数据给封装到HttpServletRequest对象中。所以,我们对request对象中的数据进行重新编码即可。

在service方法中第一行加入如下代码:

req.setCharacterEncoding("utf-8");

注意:

  1. 在Tomcat8.0及以后,不管是get请求还是post请求,都只需要设置req.setCharacterEncoding("utf-8");即可解决请求乱码。

    在Tomcat8.0之前,如果是通过get请求接收到的参数发生乱码的话,可以通过如下方式解决:

七、响应对象(HttpServletResponse)

1. response对象的介绍

1.1 作用

响应对象,用来响应浏览器发起的请求,其中封装了响应结果数据及客户端的一些信息等。

比如:客户端地址和端口号以及响应的数据类型等。


1.2 特点
  • 由Tomcat接收到请求后完成创建,并作为实参传递给对应的service方法使用。在service方法中直接调用。
  • 每次请求都会重新创建,请求结束后即销毁。
  • HttpServletResponse是一个接口,service方法接收到的是实例化对象。

2. response对象的使用

当直接调用响应对象的方法时omcat底层会将response响应的内容自动转换为HTTP协议的格式,输出给浏览器。

响应方法:

response.getWriter().writer(“响应内容”);

本质就是网络编程的流输出。

注意:响应内容可以直接是数据,也可以是数据+HTML标签+CSS样式+JS脚本。

使用response对象设置响应头:

//setHeader()方法作用:设置响应头,key相同的话,后面设置的值会覆盖前面设置的
resp.setHeader("key1", "value1");
resp.setHeader("key2", "value2");
resp.setHeader("key1", "value1_1");

//addHeader()方法作用:设置响应头,key相同的话,后面设置的值不会覆盖前面设置的
resp.addHeader("name1", "value1");
resp.addHeader("name2", "value2");
resp.addHeader("name1", "value1_1");

//下面两行代码是等价的
resp.setContentType("text/html;charset=utf-8");//设置响应的数据类型及解码方式
resp.setHeader("Content-Type", "text/html;charset=utf-8");//设置响应的数据类型及解码方式

响应数据乱码问题解决:

如果响应结果中存在中文,会在浏览器中出现乱码。因为Tomcat服务器默认使用utf-8的编码格式编码响应数据,而浏览器默认使用ISO-8859-1来解析响应数据。

resp.setContentType("text/html;charset=utf-8");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值