Servlet-入门和进阶一篇最详细

Servlet入门

Servlet说白了就是页面和java代码之间的翻译官,是sun公司提供一套页面和页面交互的规范可以说是个接口ApI,问题来了Servlet(小程序)和java中普通的ApI有什么不同之处呢?

​ servelt和普通的api像String的inputSteam区别在于他必须在tomcat服务器下运行(个人的见解)

直接上Servlet入门案例吧

需求:在IDEA编写Servlet,发布到Tomcat. 在浏览器输入路径请求, 控制台打印Hello...

  • 在helloservlet.local包下创建一个类实现Servlet接口
package helloservlet.local;

import javax.servlet.*;
import java.io.IOException;

public class ServletDemo01 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("hello");//idea控制台输出
        servletResponse.getWriter().println("hello");\\这个章不做介绍关于request和response看我另一篇专门介绍
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

​ 大家有没有疑惑呢难道真的就是实现个接口就能找到吗页面是怎么找到这个类呢?

其实Servlet并找不自己查找让我帮大家梳理一下执行的原理吧

通过上述流程图我们重点需要掌握如下几个点:

  • Servlet对象是由服务器创建(反射)

  • service()方法也是服务器调用的

  • 主要是Servlet路径的配置url-pattern

    上面案例的Servlet路径代码它写在于web.xml下的

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
               version="2.5">
    
    
        <servlet>
            <servlet-name>servletdemo01</servlet-name><!--可以取任何名字-->
            <servlet-class>helloservlet.local.ServletDemo01</servlet-class>
    
        </servlet>
        <servlet-mapping>
            <servlet-name>servletdemo01</servlet-name><!--必须和上面的一致-->
            <url-pattern>/demo01</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
    

    ​ 简单的分析一下上面的xml吧

    它是通过反射找个/demo01找仍后找个servletdemo01仍后能过找个相同名字servlet节点,找个class类的包,仍个获取里面的所以内容,里面就有service()方法调用上了。

如果大家觉得xml方式太麻烦可以通过注解的方式实现

@WebServlet("/ServletDemo02")
public class ServletDemo02 implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("hello");//idea控制台输出
        servletResponse.getWriter().println("hello");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

直接写上@WebServlet("/ServletDemo02")就可以了http://localhost:8080/ServletDemo02

servlet进阶

上面的是入门了现在大家的问题是不是更多了

第一个问题上面那么多方法为啥之调用这一个方法呢其他方法没有用嘛?

  • 其实不是的我们最常用的方法只有service()方法的如果想了解其他方法我们就要了解一下这的生命周期

    • servlet从创建到销毁的过程

      ​ 出生:(初始化)用户第一次访问时执行。

      ​ 活着:(服务)应用活着。每次访问都会执行。

      ​ 死亡:(销毁)应用卸载。

      ​ serrvlet生命周期方法:

      ​ init(ServletConfig config)

      ​ service(ServletRequest req, ServletResponse res)

      ​ destroy()

    servlet是单例多线程的, 尽量不要在servlet里面使用全局(成员)变量,可能会导致线程不安全

    单例: 只有一个对象(init()调用一次, 创建一次)

    多线程: 服务器会针对每次请求, 开启一个线程调用service()方法处理这个请求

是的servlet生命周期只有三个方法一init(初始化)那什么是被是化呢就是像static{内容}类只加载一次

service就是每调用一次就会执行一次,可以是多次

destroy()方法是指关闭tomact的时就会执行

​ 大家有没有发现url -pattern是“/demo01”难道只能这个设置吗,其实有三种设置看个人爱好了

Servlet路径的配置url -pattern

  • 第一种完全路径匹配

例如: 配置了/demo01 请求的时候必须是: /demo01 以/ 开始 访问的路径不能多一个字母也不能少一个

  • 第二种目录匹配

例如: 配置/* 访问/a, /aa, /aaa; 配置 /aa/* 访问 /aa/b , /aa/cc

**也是开始为/参数/(表示任意类型)注: Servlet里面用的 不多, 但是过滤器里面通常就使用目录匹配 **

  • 第三种扩展名匹配

例如: *.action; 访问: aa.action, bb.action, c.action; 错误写法: /*.do, 不可以写*.jsp,*.html

开始为*.action只能写action

  • 一个路径只能对应一个servlet, 但是一个servlet可以有多个路径

  • tomcat获得匹配路径时,优先级顺序:完全路径匹配> 目录匹配 > 扩展名匹配

Servlet体系结构

问题对于Servlet这个接口重写了那么多方法又不用对于不美观所以有什么好的改善办法呢

我们先看一下它的子父关系吧

我们再查阅一个Servlet接口API

由上图可知在servlet接口规范下,官方推荐使用继承的方式,继承GenericServlet 或者HttpServlet来实现接口,那么我们接下来再去查看一下这两个类的API:

  • GenericServlet 类上图

让我们实现一下

package helloservlet.local;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class GenericServletDemo1 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //你会发现只需要重要一个接口就很nice
        System.out.println("genericDemoservlet执行了");
    }
}

虽然,GenericServlet已经简化了servlet开发,但是我们平时开发程序需要按照一种互联网传输数据的协议来开发程序——http协议,因此,sun公司又专门提供了HttpServlet,来适配这种协议下的开发。

  • HttpServet类

package helloservlet.local;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/ServletDemo03")
public class ServletDemo03 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("终级版");
    }
}

​ 通过以上两个API阅读,同学们注意一个细节HttpServlet是GenericServlet的子类,它增强了GenericServlet一些功能,因此,在后期使用的时候,我们都是选择继承HttpServlet来开发servlet程序。

ServletContext知识 点

serveltContext:是一个全局对象,上下文对象

服务器为每一个应用(项目)都创建了一个ServletContext对象。 ServletContext属于整个应用的,不局限于某个Servlet。

eg: 把项目当做咱班, 把servlet当做每一位同学, 把ServletContext当做班主任

ServletContext作用

1.作为对象存取数据 让Servlet共享

2.获得文件mime类型(文件下载):类似于String.endswith(查找文件结尾类型如:.mp3,.mp4)

3.获得全局初始化参数

4.获取web资源路径

作为对象存取数据

ApI

  • getAttribute(String name);//向servletContext对象的map取数据
  • setAttribute(String name,Object object);从ServletContext对象的map中添加数据
  • removeAttribute(String name);根据name移除数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("终级版");
        //获得对象servletContext这里调用了getServletcontext()
        // 方法里面应该是new 了一个对象单例模式
        ServletContext servletContext = getServletContext();
        servletContext.setAttribute("key1","666");
        //2.调用取的方法
        String value  = (String) servletContext.getAttribute("key1");

        response.getWriter().print("ServletDemo04..."+value);

    }

获得文件mime类型

  • getMimeType(String file)
package helloservlet.local;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/Demo04")
public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //根据 文件名获得文件Mini类型
        //警告ServletContext
        //调用getmimeType()方法
        String file01 ="a.mp3";
        String file02 ="b.mp3";
        String mimeType = getServletContext().getMimeType(file01);
        String mimeType02 = getServletContext().getMimeType(file02);
        String value = (String) getServletContext().getAttribute("key1");
        resp.getWriter().print("ServletDemo05..."+mimeType+":"+mimeType02+":"+value);
        //输出得Demo05...audio/mpeg:audio/mpeg:666(audio/mpeg就是.mp3类型)
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  doGet(req,resp);
    }
}

谢谢耐心的阅读,今天又进步了哦!

欢迎讨论和留言如有错误和不好的地方请指出呀谢谢!!!

posted @ 2021-03-14 20:18  学海无芽  阅读(144)  评论(0)    收藏  举报