6.1、Servlet简介
  1. servlet是sun公司开发动态web的一门技术

  2. sum在这些API中提供了一个接口叫做:Servlet.开发的两个步骤:

    • 编写一个类,实现Servlet接口
    • 把开发好的Java类部署到web服务器中

    把实现了Servlet接口的Java程序叫做Servlet

6.2、Hello Servlet
  1. 构建普通的Maven工程,删除src目录

  2. 建立子工程

    • 这个子工程选取Maven模板中的webapp

    • 父工程:

      <modules>
      <module>demo-01</module>
      </modules>
    • 子工程:

      <parent>
      <artifactId>JavaWebLearning</artifactId>
      <groupId>org.example</groupId>
      <version>1.0-SNAPSHOT</version>
      </parent>
    • 父工程与子工程间依赖的关系类似于java的继承关系

  3. Maven环境优化:

    • 修改web.xml

      注:web.xml中的内容可以参考对应的Tomcat中的样例并与之相匹配

      <!DOCTYPE web-app PUBLIC
      "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
      "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app>
      <display-name>Archetype Created Web Application</display-name>
      </web-app>
    • 将maven的结构搭建完整:添加java和resources目录(注意Mark As)

  4. 编写一个Servlet程序

    • 编写一个普通类并继承Http

      package com.guan.servlet;
      
      import javax.servlet.http.HttpServlet;
      
      public class TestServlet extends HttpServlet {
      }

      注:这里遇到找不到HttpServlet的问题需要导入相关的依赖,可以Alt+Enter,选择Add Maven dependency,将javax.servlet.http依赖导入(前提本地的Maven仓库里有,否则需要到Maven的中央仓库下载.补充一下查找应该下载什么的思路:我们已经安装了Tomcat,而Tomcat是java开发的,既然javaweb能在里面跑肯定是由对应的jar,因此我们直接点开Tomcat的文件夹看看即可)

    • 实现Servlet接口ctrl+o选择override两个方法:doGet+doPost

      注:通常两个方法的基本逻辑是一样,所以我们可以选择直接在doPost方法中调用doGet方法

      public class TestServlet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //响应的类型:html
      resp.setContentType("text/html");
      //获取响应的输出流
      PrintWriter writer = resp.getWriter();
      writer.println("<html>");
      writer.println("<head>");
      writer.println("<title>Hello World!</title>");
      writer.println("</head>");
      writer.println("<body>");
      writer.println("<h1>12哈哈</h1>");
      writer.println("</body>");
      writer.println("</html>");
      } @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      doPost(req, resp);
      }
      }
  5. 在web.xml中注册servlet的实现类,编写Servlet的映射

    为什么要用映射:我们写的Java程序要通过浏览器访问,而浏览器要通过web服务器访问,所以我们要在web服务器中注册我们写的Servlet,还需要给它一个浏览器能访问的路径

    <!--  注册-->
    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.guan.servlet.TestServlet</servlet-class>
    </servlet> <!-- 映射-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  6. 此时你会发现程序还无法run(相关的标记是灰色的),配置Tomcat:,直接在模板中选择,有的话直接可以选择,没有的话创建一个,详见之前的博文,注意两点:

    • 点击+才是往里面添加东西
    • 需要fix一下deployment
  7. 测试

    在浏览器中查看相应的链接,发现/hello下的内容有乱码无法正常显示:12??,这是因为Java中默认的字符集是ISO8859-1,我们需要将其改为utf-8

    public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //响应的类型:html
    resp.setContentType("text/html");
    //将输出的编码格式改为utf-8
    resp.setCharacterEncoding("utf-8");
    //获取响应的输出流
    PrintWriter writer = resp.getWriter();
    writer.println("<html>");
    writer.println("<head>");
    writer.println("<title>Hello World!</title>");
    writer.println("</head>");
    writer.println("<body>");
    writer.println("<h1>12哈哈</h1>");
    writer.println("</body>");
    writer.println("</html>");
    } @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doPost(req, resp);
    }
    }
6.3、分析servlet源码:主要查看post/get方法的运作
  1. 结构:

    • 点开HttpServlet:

      public abstract class HttpServlet extends GenericServlet

      我们可以看到它继承了GenericServlet这个类

    • 继续点开GenericServlet:

      public abstract class GenericServlet implements Servlet, ServletConfig, Serializable

      我们可以看到这是一个抽象类,继承了三个接口,其中servletConfig显然是用于配置的,Seralizable是用于实体序列化的接口,所以我们重点看Servlet这个接口

    • 继续点开Servlet

      public interface Servlet {
      void init(ServletConfig var1) throws ServletException; ServletConfig getServletConfig(); void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; String getServletInfo(); void destroy();
      }

      好家伙,终于到底了!分析一下几个方法:

      • init:显然是用于初始化的
      • ServletConfig:显然是用于配置的
      • servic:没错和post/get应该就是这个,我们后面回溯主要就看这个方法
      • getServletInfo:显然是用于获得Servlet信息的
      • destory:显然是用于销毁的
  2. 回溯:

    • 查看GenericServlet抽象类:

      public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

      service方法没有被实现

    • 查看HttpServlet类:

      protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String method = req.getMethod();
      long lastModified;
      if (method.equals("GET")) {
      lastModified = this.getLastModified(req);
      if (lastModified == -1L) {
      this.doGet(req, resp);
      } else {
      long ifModifiedSince;
      try {
      ifModifiedSince = req.getDateHeader("If-Modified-Since");
      } catch (IllegalArgumentException var9) {
      ifModifiedSince = -1L;
      } if (ifModifiedSince < lastModified / 1000L * 1000L) {
      this.maybeSetLastModified(resp, lastModified);
      this.doGet(req, resp);
      } else {
      resp.setStatus(304);
      }
      }
      } else if (method.equals("HEAD")) {
      lastModified = this.getLastModified(req);
      this.maybeSetLastModified(resp, lastModified);
      this.doHead(req, resp);
      } else if (method.equals("POST")) {
      this.doPost(req, resp);
      } else if (method.equals("PUT")) {
      this.doPut(req, resp);
      } else if (method.equals("DELETE")) {
      this.doDelete(req, resp);
      } else if (method.equals("OPTIONS")) {
      this.doOptions(req, resp);
      } else if (method.equals("TRACE")) {
      this.doTrace(req, resp);
      } else {
      String errMsg = lStrings.getString("http.method_not_implemented");
      Object[] errArgs = new Object[]{method};
      errMsg = MessageFormat.format(errMsg, errArgs);
      resp.sendError(501, errMsg);
      } }

      可以看到正是这个方法完成了Post/Get等方法的实际处理

  3. 总结:

    • HttpServlet继承了GenericServlet抽象类,而GenericServlet又是继承了Servlet接口

    • HttpServlet中的Post/Get方法实际是对Servlet接口的Service方法的扩充

6.3 Servlet原理

Servlet是由服务器调用,web服务器在收到浏览器请求之后,会:

  1. 浏览器直接访问的对象是web容器(Tomcat),浏览器发起请求,web容器响应
  2. 相关的Servlet的class文件只会生成一次,后面会直接调用(所以初始化较慢
  3. web容器会产生两个对象:请求(Request)和响应(Response)
  4. 这两个对象会调用2中生成的Servlet对象的doPost/doGet方法,当然本质上是service方法
  5. Request会从service(请求)拿到请求并且把请求之后的响应交给Response
  6. 我们重写了doGet/doPost方法,web容器通过调用service方法间接地调用doGet/doPost方法

6.4、Mapping
  1. 一个Servlet可以指定一个映射路径

    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  2. 一个Servlet可以指定多个映射路径

    <!--  映射-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping> <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
  3. 一个Servlet可以指定通用映射路径

    <!--  映射-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
  4. 默认请求路径

    <!--  映射-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>
  5. 指定一些后缀

    注:此时*前面不能加映射的路径

    <!--  无法使用-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/*.hello</url-pattern>
    </servlet-mapping> <!-- 无法使用-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*.hello</url-pattern>
    </servlet-mapping> <!-- 可以使用-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.hello</url-pattern>
    </servlet-mapping>
6.5、拦截器

优先级的区别:一对一的最高,通配的其次

  1. 写好相应的Error类

    public class Test extends HttpServlet {
    
        @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html");
    PrintWriter writer = resp.getWriter();
    writer.write("<h1>404</h1>");
    } @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
    }
    }
  2. 在web.xml中注册

    <servlet>
    <servlet-name>error</servlet-name>
    <servlet-class>com.guan.servlet.Test</servlet-class>
    </servlet>
  3. 映射

    <servlet-mapping>
    <servlet-name>error</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>
6.6、ServletContext

架构:

获得:this.getServletContext():获得Servlet上下文

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

  1. 数据共享

    注:这里我们最好用一个全新的module进行演示.但是deployment有需要注意设置的地方:每一个module的deployment应该是独立的,否则如果一个deployment中有多个module,很可能会造成打包的时候把其它module也打包了.显然项目一多,打包就会显得很慢

    我们在这个Servlet中保存的数据,可以在另一个Servlet中拿到

    public class setContext extends HttpServlet {
    
        @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html");
    ServletContext context = req.getServletContext();
    String username = (String) context.getAttribute("username");
    System.out.println(username);
    } @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
    }
    }
    public class getContext extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //响应的类型:html
    resp.setContentType("text/html");
    //将输出的编码格式改为utf-8
    resp.setCharacterEncoding("utf-8");
    //获得上下文
    ServletContext context = req.getServletContext();
    context.setAttribute("username","guan");
    } @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doPost(req, resp);
    }
    }
      <servlet>
    <servlet-name>set</servlet-name>
    <servlet-class>com.guan.servlet.getContext</servlet-class>
    </servlet> <servlet>
    <servlet-name>get</servlet-name>
    <servlet-class>com.guan.servlet.setContext</servlet-class>
    </servlet> <!-- 映射--> <servlet-mapping>
    <servlet-name>set</servlet-name>
    <url-pattern>/set</url-pattern>
    </servlet-mapping> <servlet-mapping>
    <servlet-name>get</servlet-name>
    <url-pattern>/get</url-pattern>
    </servlet-mapping>

springWeb——Servlet的更多相关文章

  1. java jar包收集

    activation~与javaMail有关的jar包,使用javaMail时应与mail.jar (mail.jar和activation.jar)一起加入到lib中去,具体负责mail的数据源和类 ...

  2. 常见 jar包详解

        常见 jar包详解 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期 ...

  3. eclipse 用maven创建web项目

    Eclipse 用maven构建web项目 (2013-01-27 11:05:31) 转载▼ 标签: it eclipse maven spring web 杂谈   一.背景介绍 对于初学者,用m ...

  4. Webflux快速入门

    SpringWebflux是SpringFramework5.0添加的新功能,WebFlux本身追随当下最火的Reactive Programming而诞生的框架,那么本篇就来简述一下这个框架到底是做 ...

  5. Eclipse maven构建springmvc项目

    原文地址: http://www.cnblogs.com/fangjins/archive/2012/05/06/2485459.html 一.背景介绍 对于初学者,用maven构建项目并不是一件容易 ...

  6. Spring学习(二)——使用Gradle构建一个简单的Spring MVC Web应用程序

    1.新建一个Gradle工程(Project) 在新建工程窗口的左侧中选择 [Gradle],右侧保持默认选择,点击next,模块命名为VelocityDemo. 2.在该工程下新建一个 module ...

  7. Java常用开源jar包

    转:http://blog.csdn.net/kevingao/article/details/8125683 activation~与javaMail有关的jar包,使用javaMail时应与mai ...

  8. 【Web】Spring WebFlux

    阅读目录 一.关于WebFlux 二.SpringMVC与SpringWebFlux 三.Reactive Spring Web 四.实现WebFlux示例 SpringWebflux是SpringF ...

  9. Spring-web中的web.xml为Servlet提供的配置选项说明

    配置Servlet时可以设置的一些初始化参数,总结如下: ContextAttribute: 在ServletContext的属性中,要用作WebApplicationContext的属性名称. Co ...

随机推荐

  1. mocha_JavaScript单元测试框架

    mocha mocha是JavaScript的一种单元测试框架,既可以在浏览器环境下运行,也可以在Node.js环境下运行. 使用mocha,我们就只需要专注于编写单元测试本身,然后,让mocha去自 ...

  2. 《PHP程序员面试笔试宝典》——如何准备电话面试?

    本文摘自<PHP程序员面试笔试宝典>. PHP面试技巧分享,PHP面试题,PHP宝典尽在"琉忆编程库". 用人单位在收到简历之后,有时候由于求职者众多,而且很多求职者的 ...

  3. 今天你花里胡哨了吗 --- 定制属于自己的linux ssh迎宾信息

    请开始你的表演 linux-oz6w:~ # cat << 'eof' > /etc/profile.d/ssh-login-info.sh #!/bin/sh # 输出一个图像 e ...

  4. IDEA自带Http Client替代Postman校验接口

    对比Postman的优势 对于数据格式变动可以更为敏锐的观察到.生成的接口请求文件可以同步到代码库,支持多人使用. 使用说明 创建请求文件 使用IDEA,在项目的Scratches下创建Http Re ...

  5. IDEA一键部署SpringBoot项目到服务器

    1. 安装Alibaba Cloud Toolkit插件 2. 配置部署环境 2.1 为本次部署设置一个名字 2.2 选择被部署文件的生成方式 IDEA提供了三种方式:Maven Build,Uplo ...

  6. linux服务器登录微信报警通知

    linux服务器ssh登录安全规则中,理论上要做到:防火墙限制,hosts.allow限制,root禁止登录,用户权限分配,ssh端口修改,登录时间限制,堡垒机登录. 这里只讲登录时间限制和登录报警通 ...

  7. java 人机猜拳 游戏

    人机猜拳-游戏 掌握类和对象的使用,掌握方法的定义和返回值,掌握封装的运用 定义一个电脑类:Computer.java 点击查看[Computer.java]代码 /** * @Title: 电脑类 ...

  8. [杂记]LeTeX模板——ppt

    出处:ShareLeTeX应用模板:https://cn.sharelatex.com/project/5810ad8a07a1ab0f0f8c2ce4 代码如下: 1 % Copyright 200 ...

  9. 你别告诉我你还在用Excel做数据透视分析吧,太low了!

    来到大数据分析的时代,大量的大数据分析软件涌现,尽管如此,如果今天有人问起最常用的数据透视分析工具是什么的时候,我猜想Excel应该是大家的不二之选. 但是其实我想说,用现在的手机来打比方,Excel ...

  10. 【C# 锁】 SpinLock锁 详细分析(包括内部代码)

    OverView 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thr ...