Servlet

Server Applet

狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

  • 性能明显更好。
  • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
  • Servlet 是独立于平台的,因为它们是用 Java 编写的。
  • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
  • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

Servlet 架构

 

 

Servlet 任务

Servlet 执行以下主要任务:

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
  • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务

Servlet 的生命周期

1、执行 Servlet 构造器方法
2、执行 init 初始化方法 第一、二步,是在第一次访问,的时候创建 Servlet 程序会调用。
3、执行 service 方法 第三步,每次访问都会调用。
4、执行 destroy 销毁方法 第四步,在 web 工程停止的时候调用

 

手动实现 Servlet 程序

 

1、编写一个类去实现 Servlet 接口
2、实现 service 方法,处理请求,并响应数据
3、到 web.xml 中去配置 servlet 程序的访问地址

public class HelloServlet implements Servlet {
    /*** service 方法是专门用来处理请求和响应的
    * @param servletRequest
    * @param servletResponse 
    * @throws ServletException 
    * @throws IOException 
    */ 
    @Override 
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 
        System.out.println("Hello Servlet 被访问了");
    } 
}

通过继承 HttpServlet 实现 Servlet 程序

一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。
1、编写一个类去继承 HttpServlet 类
2、根据业务需要重写 doGet 或 doPost 方法
3、到 web.xml 中的配置 Servlet 程序的访问地址

示例代码:

public class HelloServlet2 extends HttpServlet {
    /*** doGet()在 get 请求的时候调用 
    * @param req * @param resp
    * @throws ServletException
    * @throws IOException 
    */ 
    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2 的 doGet 方法");
    }
    /*** doPost()在 post 请求的时候调用
    * @param req 
    * @param resp
    * @throws ServletException
    * @throws IOException
    */ 
    @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        System.out.println("HelloServlet2 的 doPost 方法"); 
    }
}

 

web.xml 中的配置:

<!-- servlet 标签给 Tomcat 配置 Servlet 程序 --> 
    <servlet> 
        <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class 是 Servlet 程序的全类名--> 
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class> 
    </servlet> 
    <!--servlet-mapping 标签给 servlet 程序配置访问地址-->
    <servlet-mapping> 
        <!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用--> <servlet-name>HelloServlet</servlet-name>
        <!--url-pattern 标签配置访问地址 <br/>
 / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/>
 /hello 表示地址为:http://ip:port/工程路径/hello <br/> -->
        <url-pattern>/hello</url-pattern> 
    </servlet-mapping>

 

Servlet原理

 

 

 

 

 Mapping问题

servlet-name: 名称
servlet-class:类的 全限定名
url-pattern: 作用域
作用域的写法和优先级 /*
<servlet>
<description>Cocoon blocks dispatcher</description>
<display-name>DispatcherServlet</display-name>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>com.servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

servletContext

web容器在启动的时候,他会为每个web程序都创建一个对应的 ServletContext对象,代表了当前的web应用:

共享数据

在这个servlet中保存的数据可以在另一个servlet中拿到

 

 

 

 

public class servlet extends HttpServlet {
    //由于get和post 只是请求实现方式的不同的 ,可以互相调用

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = "yyyy";

        ServletContext context = this.getServletContext();
        context.setAttribute("username",username);
        //  void setAttribute(String var1, Object var2);
        //  setAttribute 可以放任意对象

    }

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

public class getServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String) context.getAttribute("username");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().println(username);
    }

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

 

HttpServletResponse

web服务器接收到客户端的Http请求,针对这个请求 ,分别创建一个代表请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse;

  • 如果要获取客户端请求过来的参数,找HttpServletRequest
  • 如果要给客户端 响应信息,找HttpServletResponse

1、简单分类

  • 负责向浏览器发送数据的方法
resp.getWriter();
resp.getOutputStream();
  • 下载文件
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //下载文件

        //1、获取路径
        // Tomcat的文件地址在webapps 下
        String realPath = this.getServletContext().getRealPath("/xxxxxx");
        //2、下载文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
        //3、设置想办法让浏览器能够支持我们需要的东西
        resp.setHeader("Content_Disposition","attachment;filename="+fileName);
        //4、获取下载文件的输入流
        FileInputStream  in = new FileInputStream(realPath);
        //5、创建buffer缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
        //6、获取outputStream
        ServletOutputStream outputStream = resp.getOutputStream();
        //7、用FileOutputStream写入到buffer缓冲区,用outputStream把缓冲区的数据输到客户端
        while(in.read(buffer)>0){
            outputStream.write(buffer,0,len);
        }
        //关闭流
        in.close();
        outputStream.close();

    }

 

 

 

 

HttpServletRequest

 

 

ServletConfig 类

ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类。
Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。
Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对 象

 1、可以获取 Servlet 程序的别名 servlet-name 的值
2、获取初始化参数 init-param
3、获取 ServletContext 对象

 

 web.xml中的配置

<!-- servlet 标签给 Tomcat 配置 Servlet 程序 -->
<servlet> 
    <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) --> 
    <servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全类名-->
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class> 
    <!--init-param 是初始化参数--> 
    <init-param> 
        <!--是参数名-->
        <param-name>username</param-name> 
        <!--是参数值-->
        <param-value>root</param-value> 
    </init-param> 
    <!--init-param 是初始化参数--> 
    <init-param> 
        <!--是参数名-->
        <param-name>url</param-name>
        <!--是参数值--> 
        <param-value>jdbc:mysql://localhost:3306/test</param-value> 
    </init-param>
</servlet>
<!--servlet-mapping 标签给 servlet 程序配置访问地址-->
<servlet-mapping>
    <!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用--> <servlet-name>HelloServlet</servlet-name>
    <!--url-pattern 标签配置访问地址 <br/> 
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/> 
/hello 表示地址为:http://ip:port/工程路径/hello <br/> -->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

 

@Override 
    public void init(ServletConfig servletConfig) throws ServletException {
    System.out.println("2 init 初始化方法");
    // 1、可以获取 Servlet 程序的别名 servlet-name 的值
    System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName());
    // 2、获取初始化参数 init-param 
    System.out.println("初始化参数 username 的值是;" + servletConfig.getInitParameter("username"));
    System.out.println("初始化参数 url 的值是;" + servletConfig.getInitParameter("url"));
    // 3、获取 ServletContext 对象 
    System.out.println(servletConfig.getServletContext());
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-05-09 21:59  爱吃番茄炒鸡蛋  阅读(85)  评论(0)    收藏  举报