《遇见狂神说》Javaweb之Servlet技术

Posted 生命是有光的

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《遇见狂神说》Javaweb之Servlet技术相关的知识,希望对你有一定的参考价值。

0.概述

  1. Servlet笔记,复习回顾使用
  2. 秦疆老师配套视频直达Javaweb入门到实战

1.Servlet

1.1Servlet简介

  • Servlet就是sun公司开发动态web的一门技术

  • Sun在API中提供了一个接口:Servlet ,如果逆向开发一个Servlet程序,只需要完成两个小步骤

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

1.2HelloServlet

  1. 构建一个普通的Maven项目

在这里插入图片描述

在这里插入图片描述

  1. 删掉里面的Src目录,这个空的工程就是Maven主工程

  2. pom.xml 里面添加 servlet,jsp 依赖

    • Maven Repository仓库里面搜索 javax-servlet-api 和 javax.servlet.jsp-api

    在这里插入图片描述

    <dependencies>
            
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    
    
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
    
        
    </dependencies> 
    
  3. Load Maven changes

在这里插入图片描述

  1. 新建Module

    在这里插入图片描述

在这里插入图片描述

  1. 父项目的pom.xml文件有
<modules>
        <module>servlet-01</module>
</modules>
  1. 子项目的pom.xml文件有
<parent>
        <artifactId>javaweb-02-maven</artifactId>
        <groupId>com.kuang</groupId>
        <version>1.0-SNAPSHOT</version>
</parent>

父项目中的java子项目可以直接使用,意思其实就是子项目可以不用再次导入jar包,直接可以使用父项目导入的jar包

7.在 main 目录下新建Directory javaresources

​ 并且右键-Mark Directory as ,分别转换为java目录和资源目录

在这里插入图片描述

  1. Maven环境优化

    • 修改web.xml为最新的

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
              http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
              version="4.0"
              metadata-complete="true">
      </web-app>
      

上面这一大串我们是从哪里来的呢?其实我们是在tomcat\\webapps\\ROOT\\WEB-INF\\web.xml 中与tomcat相对应的版本

  1. 新建包,新建类

在这里插入图片描述

  1. 写一个Servlet程序,Serlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServlet
  • 编写一个普通类
  • 实现Servlet接口,这里我们直接继承HttpServlet
  • 重写doGet、doPost方法
  • 编写Servlet的映射

为什么需要映射?

  • 我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径

2.继承HttpServlet

public class HelloServlet extends HttpServlet {
    // get或者post只是请求实现的不同方式,可以互相调用,业务逻辑都一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入doGet方法");
        // 在这边重写完方法之后就去web.xml里面编写Servlet的映射
    }

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

3.编写Servlet的映射

<!--    1.注册servlet-->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--    servlet的请求路径-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. 配置并启动tomcat

在这里插入图片描述

在这里插入图片描述

  1. 请求我们自己映射的/hello

在这里插入图片描述

1.3Mapping问题

  1. 一个Servlet可以指定一个映射路径
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello-->
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. 一个Servlet可以指定多个映射路径
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello2-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello3-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello3</url-pattern>
</servlet-mapping>
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello4-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello4</url-pattern>
</servlet-mapping>
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello5-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello5</url-pattern>
</servlet-mapping>
  1. 一个Servlet可以指定通用映射路径
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello/****-->
<!--	****代表任何字母数字均可	-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  1. 默认请求路径
<!--默认请求路径-->
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/****-->
<!--	****代表任何字母数字均可	-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
  1. 指定一些后缀或者前缀等等….
<!--可以自定义后缀实现请求映射-->
<!--注意点,*前面不能加项目映射的路径-->
<!--当我们这样配置映射路径的时候,我们访问的名称为:localhost:8080/s1/hello/****.qinjiang-->
<!--  例如:localhost:8080/s1/hello/sajdlkajda.qinjiang	-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.qinjiang</url-pattern>
</servlet-mapping>
  1. 优先级问题
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
</servlet-mapping>

<!--404-->
<servlet>
    <servlet-name>error</servlet-name>
    <servlet-class>com.kuang.servlet.Error</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>error</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

例如当我们配置上方映射时候,我们访问:localhost:8080/s1/hello ,思考此时是访问/*还是访问/hello呢?

  • 答案是访问/hello
  • 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求

2.ServletContext

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

白话:代表整个web应用,可以和程序的容器(服务器)来通信

2.1共享数据

  • 我们在这个Servlet中保存的数据,可以在另外一个servlet中拿到
  • 但是都是通过同一个ServletContext对象拿到的
    • context.setAttribute(String name,Object value)
    • context.getAttribute(String name)

HelloServlet.java

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //数据
        String username = "秦疆"; 
         //将一个数据保存在了ServletContext中,名字为:username 。值 username
        context.setAttribute("username",username);

    }
}
  • 编写mapper映射
<!--    存放username数据	-->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

GetServlet.java

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().print("名字"+username);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 编写mapper映射
<!--    获取username数据-->
<servlet>
    <servlet-name>getc</servlet-name>
    <servlet-class>com.kuang.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>getc</servlet-name>
    <url-pattern>/getc</url-pattern>
</servlet-mapping>

测试访问结果;

  • 先输入 : http://localhost:8080/s2/hello 访问/hello会存放数据
  • 再输入:http://localhost:8080/s2/getc 访问/getc会取出数据

在这里插入图片描述

在这里插入图片描述

2.2获取初始化参数(了解)

我们可以在web.xml中配置一些web应用初始化参数,在ServletContext对象中可以拿到它

GetInitParameter.java

/**
 * 获取初始化参数
 */
public class GetInitParameter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");
        // 将获取到的url打印到网页上
        resp.getWriter().print(url);
    }

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

在web.xml中配置初始化参数和注册servlet映射为 /gp

<!--    配置初始化参数 参数为url,值为 jdbc:mysql://localhost:3306/mybatis  -->
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<!--   注册servlet映射 -->
    <servlet>
        <servlet-name>gp</servlet-name>
        <servlet-class>com.kuang.servlet.GetInitParameter</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>gp</servlet-name>
        <url-pattern>/gp</url-pattern>
    </servlet-mapping>
</web-app>
  • 我们访问测试

在这里插入图片描述

2.3请求转发

GetRequestDispatcher.java

/**
 * 请求转发
 */
public class GetRequestDispatcher extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了GetRequestDispatcher");
        ServletContext context = this.getServletContext();
        //RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); 转发的请求路径
        //requestDispatcher.forward(req,resp); 调用forward实现请求转发;
        context.getRequestDispatcher("/gp").forward(req,resp);

    }

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

在web.xml中配置servlet映射为 /gr

<!--    请求转发    -->
<servlet>
    <servlet-name>gr</servlet-name>
    <servlet-class>com.kuang.servlet.GetRequestDispatcher</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>gr</servlet-name>
    <url-pattern>/gr</url-pattern>
</servlet-mapping>
  • 测试访问

在这里插入图片描述

原因:我们请求/gr,但是/gr通过getRequestDispatcher转发到另外一个页面,但是我们访问的路径不变,依旧是localhost:8080/s2/gr

请求转发的特点:

  1. 浏览器地址栏路径不发生变化
  2. 只能转发到当前服务器内部资源中
  3. 转发是一次请求

请求转发:A想要拿到C中的资源,但是A没法与C连接,A只能与B连接,于是A对B说,B你去C里面给我拿,B就与C建立连接,C把资源给B,B再把资源给A

重定向:A连接B说想要拿到C中的资源,B对A说,你去连接C然后拿资源

2.4读取资源文件

  • 在resources目录下新建db.properties

db.properties

username=root12312
password=zxczxczxc

PropertiesServlet.java

/**
 * 读取资源文件properties
 */
public class PropertiesServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        // 思路:需要一个文件流
        // 这里的路径:
        InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties prop = new Properties();
        prop.load(is);

        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        resp.getWriter().print(username +":"+password );

    }

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

  • 这里的路径示意图
  • 因为java目录和resources目录均被打包至classes目录

在这里插入图片描述

  • 去web.xml中配置servlet映射
<!--    获取资源文件properties    -->
<servlet>
    <servlet-name>pr</servlet-name>
    <servlet-class>com.kuang.servlet.PropertiesServlet</servlet-class>
</servlet>
以上是关于《遇见狂神说》Javaweb之Servlet技术的主要内容,如果未能解决你的问题,请参考以下文章

《遇见狂神说》Javaweb之cookie和session

遇见狂神说---JavaWeb部分笔记

狂神说 javaweb

遇见狂神说 --- [ 文件上传,邮件发送实现 ]

《遇见狂神说》全套JDBC技术总结

遇见狂神说JAVA笔记 --- Mybatis 学习