一 : Servlet的定义

Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app.

Java Servlet 是运行在 Web服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页 .

Servlet用于开发动态页面 , 根据用户输入内容的不同 , 来返回出不同的页面结果 .

什么是动态页面 , 什么是静态页面呢 ?

  • 静态页面也就是内容始终固定的页面. 即使用户不同/时间不同/输入的参数不同 , 页面内容也不会发生 ;
    变化. (除非网站的开发人员修改源代码, 否则页面内容始终不变).
  • 动态页面指的就是 用户不同/时间不同/输入的参数不同, 页面内容会发生变化 .

在这里插入图片描述

在这里插入图片描述

二 : Servlet的任务

  1. 允许程序猿注册一个类, 在 Tomcat 收到某个特定的 HTTP 请求的时候, 执行这个类中的一些代码.
  2. 帮助程序猿解析 HTTP 请求, 把 HTTP 请求从一个字符串解析成一个 HttpRequest 对象.
  3. 帮助程序猿构造 HTTP 响应. 程序猿只要给指定的 HttpResponse 对象填写一些属性字段, Servlet就会自动安装 HTTP 协议的方式构造出一个 HTTP 响应字符串, 并通过 Socket 写回给客户端.
  4. 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  5. 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

三 : 写一个简单的Servlet程序

一共需要七大步骤 .

2.1创建项目

在这里插入图片描述

maven叫做"构建工具" , 针对代码进行依赖管理 , 编译 , 打包 , 验证 , 部署等功能 , 可以视为是针对复杂项目进行管理的一个解决方案 .

maven自身的功能是很多的 , 我们主要使用 :

  1. 管理依赖 : 想使用某个第三方库,就使用maven把这个库下载下来并导入到项目中 .
  2. 打包 : 把代码编译好,把.class 文件打成压缩包(.jar 或者.war) .

在这里插入图片描述

2.2 引入依赖

此处谈到的依赖 , 是编写Servlet程序所需要的依赖(Servlet的jar包) , 需要把这个jar下载导入到项目中 .

下载步骤 :

  1. 打开 Maven的中央仓库
  2. 找到我们所需要的内容 :

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 把这段文字 , 粘贴到pom.xml里面 .

在这里插入图片描述
注意 : 首次使用 , 会标红 , 这是因为在首次使用时 , maven会从中央视仓库下载对应的jar包 , 这需要一定的时间 . 你也可是点击刷新 , 主动触发下载 !

在这里插入图片描述
在这里插入图片描述

2.3 创建目录

在这里插入图片描述
将下面的内容复制粘贴到web.xml中 .

<!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>

webapp 目录就是未来部署到 Tomcat 中的一个重要的目录. 当前我们可以往 webapp 中放一些静态资源, 比如 html , css 等.

在这个目录中还有一个重要的文件 web.xml. Tomcat 找到这个文件才能正确处理 webapp 中的动态资源.

2.4编写代码

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("/hello")
public class HelloServet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello world");
        resp.getWriter().write("hello world");
    }
}

在这里插入图片描述

doGet()方法不是咱们自己手动调用的 , 而是Tomcat自动调用的 , Tomcat 会自动的识别出合适的时机,来自动调用doGet方法 , —定是通过GET请求触发的!!! doGet做的工作,就是Tomcat收到请求之后,到返回响应之前,中间的过程 !

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@WebServlet 属于类级别的注解,标注在继承了 HttpServlet 的类之上。常用的写法是将 Servlet 的相对请求路径(即 value)直接写在注解内 .

上述代码没有main方法 , 不能单独执行,main方法在Tomcat内 , 上述代码需要部署到Tomcat中,由Tomcat进行调用.main好比汽车的发动机 , 我们写的Servlet代码就是车厢 . 只有个车头 , 可以自己跑 ; 但是车厢直接不能跑 , 得挂在车头上 .

在这里插入图片描述

2.5 打包

借助maven , 一键式完成 !

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
再次双击package进行打包 !

在这里插入图片描述

2.6 部署

把刚才得到的war包 , 拷贝到Tomcat的webapps目录中 !

在这里插入图片描述

2.7 验证

让浏览器构造一个HTTP Get请求 !

在这里插入图片描述
注意目录结构:
在这里插入图片描述

总结 :

在这里插入图片描述

注意 : Spring Boot可以简化这里的流程 , 现在先介绍一种中间的方案 , 即借助IDEA中的一个插件 , Smart Tomcat , 来简化打包和部署 .

在这里插入图片描述
在这里插入图片描述

smart tomcat不是tomcat , 其功能就是能够在IDEA中调用tomcat , 我们就无需手动双击tomcat的启动脚本来运行 , 而是直接在IDEA中一点就能运行tomcat了 .

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击运行, 会在IDEA中显示tomcat的日志 .

在这里插入图片描述

此处中文也不再乱码了 !

在这里插入图片描述

smart tomcat的工作原理 , 和前面的手动拷贝部署不太一样 , 是让tomcat直接加载了我们代码中的webapp目录 , 这时候就跳过了打包 + 拷贝的过程 , 但是也起到了部署的效果 !

常见错误集合 :

  1. 404 : 大概率是URL写错了 , 也可能是webapp未正确加载(比如web.xml写错了) .
  2. 405 : method not allowed , 发送GET请求但未实现doGet() , 或实现了doGet() , 但未把super.doGet这个代码删掉 ;
  3. 505 : 服务器内部错误 , 即服务器挂了 , 这说明你的代码中抛出了异常 .
  4. 返回空白页面 , 大概率是未执行write()方法 .
  5. 无法访问此网站 , 大概率是tomcat没有正确启动 .

Tomcat 的定位

上面的实现是在tomcat的基础上实现的 .

HTTP 协议作为一个应用层协议, 需要底层协议栈来支持工作. 如下图所示 :

在这里插入图片描述
更详细的交互过程见下图 :

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四 : Servlet API 详解

重点关注三个类 !

在这里插入图片描述

4.1HttpServlet

4.1.1核心方法

在这里插入图片描述

  • init只会在该Servlet类第一次被使用的时候调用到 , 相当于是用来初始化 ;
  • destroy是在Servlet对象被销毁的时候才会调用到 , 仅调用一次 , 相当于收尾工作 . 这个方法不一定能执行到 , 仅在tomcat是通过8005端口进行关闭时会执行destroy , 如果是直接杀死tomcat进程 , 则不会调用 .
  • service在每次收到请求(无论什么方法)时都会调用到service , 默认父类的service里面就会根据方法调用doGet/doPost .

最常用的 : doXXX系列!!!

这些方法的调用时机, 就称为 “Servlet 生命周期”. (也就是描述了一个 Servlet 实例从生到死的过程).

在这里插入图片描述

4.1.2构造POST请求

前面我们通过在浏览器里输入url构造了GET请求 , 那POST请求该如何构造呢 ?

form可以支持get和post , 在此处我们可以使用ajax .

在这里插入图片描述
在这里插入图片描述

加载 : jQuery

在这里插入图片描述

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("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet!");
        resp.getWriter().write("doGet!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost!");
        resp.getWriter().write("doPost!");
    }

}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
    <script>
        $.ajax({
           type:'post',
           url:'hello',
           //url:'/hello_servlet/hello',
            success:function(body){
                console.log(body);
            }
        });
    </script>
</body>
</html>

在这里插入图片描述

此处我们只在控制台看到了响应 , 在控制台打印了"doPost!" , 这是因为ajax拿到的响应数据,是根据回调函数的方法处理的 , 可以显示 , 也可以不显示 ; 而直接通过浏览器输入url得到的响应内容是直接被浏览器渲染到页面上的 .

路径问题

如何把内容打印到页面上呢 ?

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("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet!");
        resp.getWriter().write("doGet!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost!");
        resp.getWriter().write("doPost!");
    }

}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .one{
            font-size: 50px;
            color: aqua;
        }
    </style>
</head>
<body>
    <div class="one"></div>
    <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
    <script>
        $.ajax({
           type:'post',
           url:'hello',
            success:function(body){
                //console.log(body);
                let div = document.querySelector('.one');
                div.innerHTML = body;
            }
        });
    </script>
</body>
</html>

在这里插入图片描述

根据当前的请求"doPost" , 决定调用我们自己代码中的doGet方法!!!

在进行这部分操作时 , 一开始出现了下面的问题 , 显示报错信息为 :

无法在地址[localhost]和端口[8005]上创建服务器关闭套接字(基本端口[8005]和偏移量[0]).

经过查阅资料 , 发现这是端口占用导致的问题 . 解决方案如下 :

  1. 查看端口占用
    在windows命令行窗口下执行:netstat -aon|findstr “8080”

在这里插入图片描述
端口“8080”被PID(进程号)为16160的进程占用 .

  1. 查看端口“8080”被哪个应用占用,,继续执行下面命令:tasklist|findstr “16160”

在这里插入图片描述

3.关闭进程(此处按进程名关闭进程) : taskkill /im java.exe

在这里插入图片描述

扩展 : 关闭进程的方式 :

  1. 按进程号关闭进程 taskkill /pid 2152
    多个时格式为:taskkill /pid 2152 /pid 1284 / …
  2. 按进程名关闭进程 如要关闭notepad.exe,格式为:taskkill /im notepad.exe
    指定多个时格式为:taskkill /im notepad.exe /im iexplorer.exe / im…
    如果是要关闭所有的,则使用通配符*,即:taskkill /im *.exe
  3. 有提示的关闭进程 taskkill /t /im notepad.exe
    taskkill /t /pid 2152
    这个效果是提示后在使用者确定后关闭,有提示框。
  4. 强行终止进程 taskkill /f /im notepad.exe
    taskkill /f /pid 2152

被拒绝时 , 尝试使用命令行 taskkill /f /t /im java.exe,可以关闭,亲测可用 .

通过按钮触发ajax请求的发送 :

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("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet!");
        resp.getWriter().write("doGet!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost!");
        resp.getWriter().write("doPost!");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPut!");
        resp.getWriter().write("doPut!");
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doDelete!");
        resp.getWriter().write("doDelete!");
    }
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .one{
            font-size: 50px;
            color: aqua;
        }
    </style>
</head>
<body>
    <div class="one"></div>

    <button id="doGet">get</button>
    <button id="doPost">post</button>
    <button id="doPut">put</button>
    <button id="doDelete">delete</button>
    <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
    <script>
        let doGetBtn = document.querySelector('#doGet');
        doGetBtn.onclick = function(){
            $.ajax({
           type:'get',
           url:'hello',
            success:function(body){
                let div = document.querySelector('.one');
                div.innerHTML = body;
            }
        });
        }

        let doPostBtn = document.querySelector('#doPost');
        doPostBtn.onclick = function(){
            $.ajax({
           type:'post',
           url:'hello',
            success:function(body){
                //console.log(body);
                let div = document.querySelector('.one');
                div.innerHTML = body;
            }
        });
        }

        let doPutBtn = document.querySelector('#doPut');
        doPutBtn.onclick = function(){
            $.ajax({
           type:'put',
           url:'hello',
            success:function(body){
                //console.log(body);
                let div = document.querySelector('.one');
                div.innerHTML = body;
            }
        });
        }

        let doDeleteBtn = document.querySelector('#doDelete');
        doDeleteBtn.onclick = function(){
            $.ajax({
           type:'delete',
           url:'hello',
            success:function(body){
                //console.log(body);
                let div = document.querySelector('.one');
                div.innerHTML = body;
            }
        });
        }

    </script>
</body>
</html>

在这里插入图片描述

注意文件位置 :

在这里插入图片描述

Q : 当前使用ajax构造出了上述几种请求.但是还是比较麻烦.毕竟要写代码 . 是否有办法,不写代码,也能构造出任意的http请求呢?

A : 此处还可以使用第三方工具,来构造HTTP请求. (类似功能的工具种类繁多),咱们在工作中一个非常常用的,叫做 PostMan(各种请求都能构造 , 真香) . Postman本来是chrome的一个插件.现在已经是独立的程序了 . 可以去官网下载安装 !

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
简单演示用法 :

在这里插入图片描述

在这里插入图片描述

Q : 面试题 : 谈谈HttpServlet的生命周期 ?

A :

  1. 首次使用 , 先调用一次init ;
  2. 每次收到请求 , 调用service , 在service内部通过具体方法来决定调用哪个doXXX代码 ;
  3. 销毁之前调用destroy .

4.2 HttpServletRequest

在这里插入图片描述

这个类就提供了一组方法 , 让我们能够获取到HTTP请求中的这些信息 .

4.2.1 核心方法

在这里插入图片描述
在这里插入图片描述

4.2.2实例

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;
import java.util.Enumeration;

@WebServlet("/requestServlet")
public class RequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(req.getProtocol());//返回请求协议的名称和版本
        stringBuilder.append("<br>");
        stringBuilder.append(req.getMethod());//返回请求的HTTP方法的名称
        stringBuilder.append("<br>");
        stringBuilder.append(req.getRequestURI());//返回请求的URL的一部分
        stringBuilder.append("<br>");
        stringBuilder.append(req.getQueryString());//返回包含在路径后的请求URL中的查询字符串
        stringBuilder.append("<br>");
        Enumeration<String> headersnames = req.getHeaderNames();
        while(headersnames.hasMoreElements()){
            String name = headersnames.nextElement();
            stringBuilder.append(name+":"+req.getHeader(name));
            stringBuilder.append("<br>");
        }
        //设置Content Type
        resp.setContentType("test/html;charset=utf8");
        resp.getWriter().write(stringBuilder.toString());
    }
}

在这里插入图片描述

更多的情况下 , 需要通过API拿到请求中传来的必要的参数 !!! 假如教务系统上 , 需要获取某个同学的信息 , 给服务器发个请求 :

 /studentInfo?classId=368&studentId=20

此时服务器就需要知道传过来的信息是什么 .

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;
class Student{
    public int classId;
    public int studentId;
}
@WebServlet("/studentInfo")
public class StudentInofoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 假设客户端发来的请求形如 /studentInfo?classId=368&studentId=20
        // 就可以通过 getParameter 方法来拿到这两个 id 的值.
        resp.setContentType("text/html,charset=utf8");
        String queryString = req.getQueryString();
        System.out.println(queryString);
        String classId = req.getParameter("classId");
        String studentId = req.getParameter("studentId");
        System.out.println("classId: " + classId + "studentId: " + studentId);
        resp.getWriter().write("classId: " + classId + "studentId: " + studentId);
    }
}

在这里插入图片描述

在这里插入图片描述

getParameter的效果就是拿到query string中的键值对 , 根据key获取value(key和value都是String类型的) .

前端除了通过query string来传参 , 还有其他的传参方式 , 比如可以通过post请求 , 通过body来传参到服务器 .

在这里插入图片描述

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;
import java.util.function.DoublePredicate;

class Student{
    public int classId;
    public int studentId;
}
@WebServlet("/studentInfo")
public class StudentInofoServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 约定 body 使用 application/x-www-form-urlencoded 这种格式来传参.
        // 这个格式就形如 classId=368&studentId=05
        // 这个格式和 query string 相同!!! 只是数据是在 body 中!
        // 针对这种格式, 获取到值的方式, 仍然是 getParameter !!!!
        resp.setContentType("text/html,charset=utf8");
        String queryString = req.getQueryString();
        System.out.println(queryString);
        String classId = req.getParameter("classId");
        String studentId = req.getParameter("studentId");
        System.out.println("classId: " + classId + " studentId: " + studentId);
        resp.getWriter().write("classId: " + classId + " studentId: " + studentId);
    }
}

通过Postman构造POST请求 :

在这里插入图片描述

使用Fiddler抓包的结果 :

在这里插入图片描述
还可以通过form构造请求 :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>通过form构造请求</title>
</head>
<body>
    <form action="studentInfo" method="post">
            <input type="text" name="classId">
            <input type="text" name="studentId">
            <input type="submit" name="提交">
    </form>
</body>
</html>

在这里插入图片描述
如果 POST 请求中的 body 是按照 JSON 的格式来传递, 那么获取参数的代码就要发生调整.

在这里插入图片描述
结果是这样的 :

在这里插入图片描述
显然我们没法正确解析 .

如果我们自己写代码按照字符串解析的方式获取到这里的键值对 , 是很费劲的 , 所以我们选择使用第三方库 . Java世界中有很多处理Json的第三方库 , 此处我们使用Jackson . (Spring官方推荐使用且内部集成了) .

打开 maven中央仓库

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

将依赖下载到本地 : (点击刷新)

在这里插入图片描述
在这里插入图片描述

此时 , maven就把这个库给下载到了本地 .

在这里插入图片描述

对于jackson , 只需要掌握两个操作 :

  • 把json格式的字符串转化为Java对象 ;
  • 把Java对象转成json字符串 .

对应到一个类ObjectMapper .

import com.fasterxml.jackson.databind.ObjectMapper;

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;
import java.util.function.DoublePredicate;

class Student{
    public int classId;
    public int studentId;
}
@WebServlet("/studentInfo")
public class StudentInofoServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //处理json格式的请求
        ObjectMapper objectMapper = new ObjectMapper();
        //使用readValue把json字符串转成Java对象
        Student student = objectMapper.readValue(req.getInputStream(),Student.class);
        System.out.println(student.classId+","+student.studentId);
        resp.getWriter().write(student.classId+","+student.studentId);
        
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

加入json中的key和类里的属性不一致, 会发生什么?

在这里插入图片描述

此时出现内部服务器错误 .

4.3 HttpServletResponse

Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到
HttpServletResponse 对象中. 然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过Socket 写回给浏览器.

4.3.1 核心方法

在这里插入图片描述

注意 : Request是get系列的方法, Response则是一些set系列的方法.

在这里插入图片描述
简单演示上述API :

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("/status")
public class StatusCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置相应的状态码
        resp.setStatus(500);
    }
}

在这里插入图片描述

代码示例 : 自动刷新

给响应报文header设置Refresh属性 , 跟上的value表示让浏览N秒之后刷新 .

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("/refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Refresh","1");
        resp.getWriter().write(System.currentTimeMillis()+"");
    }
}

在这里插入图片描述
显示时间戳, 每隔1秒刷新一次 .

实际运用: 文字直播 .

在这里插入图片描述

代码示例: 重定向

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("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(302);//3xx表示重定向, 默认用302
        resp.setHeader("Location","https://www.baidu.com");

        /*
         另一种简单的写法
         resp.sendRedirect("https://www.baidu.com");
         */
    }
}

在这里插入图片描述

简单总结 :
在这里插入图片描述

五 :应用—留言板

效果回顾 :

在这里插入图片描述

当前这些数据只是在浏览器的内存中保存着 , 一旦浏览器重启或刷新页面 , 数据就消失了 .

解决方案就是把数据保存在服务器上 .

5.1准备工作

  1. 创建好项目 ;
  2. 构建好目录 ;
  3. 引入依赖 ;
  4. 把留言板项目拷贝到项目中 .

在这里插入图片描述
这个html应该放在webapp目录下 .

此时我们就可以换一种打开方式了 .

5.2 约定好前后端交换的接口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.3 实现提交数据

在这里插入图片描述

编写前端请求代码(第3部分)

                //5.[新步骤]需要把刚才输入框里取到的数据, 构造成 POST 请求, 交给后端服务器!
                let messageJson = {
                    "from" : from,
                    "to" : to,
                    "message" : message
                };
                $.ajax({
                    type:"post",
                    url:'message',//或者写url='/MessageWall/message'
                    contentType:"application/json;charset=utf8",
                    data:JSON.stringify(messageJson),
                    success:function(body){
                        alert("提交成功!");
                    },
                    error:function(){//在服务器返回的状态码不是2xx时触发这个error
                        alert("提交失败!");
                    }
                });
 

在这里插入图片描述

整体代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>留言板</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        .container {
            width : 800px;
            margin : 10 px auto;
        }

        .container h2 {
            text-align: center;
            margin: 30px 0px;
        }

        .row {
            height: 50px;
            display: flex;
            justify-content: center;
            margin-top: 5px;
            line-height: 50px;
        }

        .row span {
            height: 50px;
            width: 100px;
            line-height: 50px;
        }

        .row input {
            height: 50px;
            width: 300px;
            line-height: 40px;
            font-size: 30px;
            color: cadetblue;
        }

        .row button {
            width: 400px;
            height: 50px;
            color: #000;
            background-color: aquamarine;
            border: none;
            border-radius: 10px;
        }

        .row button:active {
            background-color: grey;
        }
    </style>
</head>
<body>
    <!--这是一个顶层容器,放其他元素-->
    <div class="container">
        <h2>留言板</h2>
        <div class="row">
            <span></span>
            <input type="text" id="from">
        </div>

        <div class="row">
            <span>对谁</span>
            <input type="text" id="to">
        </div>

        <div class="row">
            <span>说什么</span>
            <input type="text" id="message">
        </div>

        <div class="row">
            <button>提交</button>
        </div>

        <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
        <script>
            let container = document.querySelector('.container');
            let fromInput = document.querySelector('#from');
            let toInput = document.querySelector('#to');
            let messageInput = document.querySelector('#message');
            let button = document.querySelector('button');
            button.onclick = function() {
                //1.把用户输入的内容获取到
                let from = fromInput.value;
                let to = toInput.value;
                let message = messageInput.value;
                if(from == '' || to == '' || message == ''){
                    return;
                }
                //2.构造一个div,把这个div插入到.container的末尾
                let newDiv = document.createElement('div');
                newDiv.className = 'row';
                newDiv.innerHTML = from + "对" + to + "说" + message;
                //3.把div挂在container里面
                container.appendChild(newDiv);
                //4.把之前输入框中的内容清空
                fromInput.value = '';
                toInput.value = '';
                messageInput.value = '';

                //5.[新步骤]需要把刚才输入框里取到的数据, 构造成 POST 请求, 交给后端服务器!
                let messageJson = {
                    "from" : from,
                    "to" : to,
                    "message" : message
                };
                $.ajax({
                type: 'post',
                contentType: 'application/json;charset=utf8',
                url: 'message',// 绝对路径的写法url: '/MessageWall/message',
                data: JSON.stringify(messageJson),
                success: function(body) {
                    alert("提交成功!");
                },
                error: function() {// 会在服务器返回的状态码不是 2xx 的时候触发这个 error. 
                    alert("提交失败!");
                }
            });
        }

        </script>
</body>
</html>

编写后端响应代码(第4部分)

在这里插入图片描述

import com.fasterxml.jackson.databind.ObjectMapper;

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;
import java.util.ArrayList;
import java.util.List;

//对应前端传来的请求body
//保证这几个属性的名字都和json里的key对应
class Message{
    public String from;
    public String to;
    public String message;

    @Override
    public String toString() {
        return "Message{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    private List<Message> messageList = new ArrayList<>();
    //负责实现让客户端提交数据给服务器
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.把body的json数据解析出来
        Message message = objectMapper.readValue(req.getInputStream(),Message.class);
        //2.把这个对象保存起来,最简单的方法,就是存到内存中.
        messageList.add(message);
        System.out.println("message : " + message);
        //3.返回保存成功的响应
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write("{\"ok\" : 1}");
    }

    //负责实现让客户端从服务器拿到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }

}

使用Fiddler , 来查看结果 :

在这里插入图片描述

编写后端请求代码(第1部分)

在这里插入图片描述

    //负责实现让客户端从服务器拿到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        //把对象转成json格式的字符串,此处messageList是一个List,直接被转成json数组
        String respString = objectMapper.writeValueAsString(messageList);
        resp.getWriter().write(respString);
    }

整体代码

import com.fasterxml.jackson.databind.ObjectMapper;
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;
import java.util.ArrayList;
import java.util.List;

//对应前端传来的请求body
//保证这几个属性的名字都和json里的key对应
class Message{
    public String from;
    public String to;
    public String message;

    @Override
    public String toString() {
        return "Message{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    private List<Message> messageList = new ArrayList<>();
    //负责实现让客户端提交数据给服务器
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.把body的json数据解析出来
        Message message = objectMapper.readValue(req.getInputStream(),Message.class);
        //2.把这个对象保存起来,最简单的方法,就是存到内存中.
        messageList.add(message);
        System.out.println("message : " + message);
        //3.返回保存成功的响应
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write("{\"ok\" : 1}");
    }

    //负责实现让客户端从服务器拿到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        //把对象转成json格式的字符串,此处messageList是一个List,直接被转成json数组
        String respString = objectMapper.writeValueAsString(messageList);
        resp.getWriter().write(respString);
    }

}

编写前端响应代码(第2部分)在这里插入图片描述

 /*
        这个函数在页面加载时,从服务器获取到当前的消息列表
        并显示到页面上
        */
       function load(){
        $.ajax({
            type:'get',
            url:'message',
            success:function(body){
                /*
                此处得到的body是一个js对象的数组了
                本来服务器返回的是JSON格式的字符串,ajax会自动根据
                Content-Type对响应的body进行解析,解析成js对象
                */
               let container = document.querySelector('.container');
               for(let message of body){
                let newDiv = document.createElement('div');
                newDiv.className = 'row';
                newDiv.innerHTML = message.from + "对" + message.to + "说" +  message.message;
                container.appendChild(newDiv); 
               }
            }
        });

整体代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>留言板</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        .container {
            width : 800px;
            margin : 10 px auto;
        }

        .container h2 {
            text-align: center;
            margin: 30px 0px;
        }

        .row {
            height: 50px;
            display: flex;
            justify-content: center;
            margin-top: 5px;
            line-height: 50px;
        }

        .row span {
            height: 50px;
            width: 100px;
            line-height: 50px;
        }

        .row input {
            height: 50px;
            width: 300px;
            line-height: 40px;
            font-size: 30px;
            color: cadetblue;
        }

        .row button {
            width: 400px;
            height: 50px;
            color: #000;
            background-color: aquamarine;
            border: none;
            border-radius: 10px;
        }

        .row button:active {
            background-color: grey;
        }
    </style>
</head>
<body>
    <!--这是一个顶层容器,放其他元素-->
    <div class="container">
        <h2>留言板</h2>
        <div class="row">
            <span></span>
            <input type="text" id="from">
        </div>

        <div class="row">
            <span>对谁</span>
            <input type="text" id="to">
        </div>

        <div class="row">
            <span>说什么</span>
            <input type="text" id="message">
        </div>

        <div class="row">
            <button>提交</button>
        </div>

        <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
        <script>
            let container = document.querySelector('.container');
            let fromInput = document.querySelector('#from');
            let toInput = document.querySelector('#to');
            let messageInput = document.querySelector('#message');
            let button = document.querySelector('button');
            button.onclick = function() {
                //1.把用户输入的内容获取到
                let from = fromInput.value;
                let to = toInput.value;
                let message = messageInput.value;
                if(from == '' || to == '' || message == ''){
                    return;
                }
                //2.构造一个div,把这个div插入到.container的末尾
                let newDiv = document.createElement('div');
                newDiv.className = 'row';
                newDiv.innerHTML = from + "对" + to + "说" + message;
                //3.把div挂在container里面
                container.appendChild(newDiv);
                //4.把之前输入框中的内容清空
                fromInput.value = '';
                toInput.value = '';
                messageInput.value = '';

                //5.[新步骤]需要把刚才输入框里取到的数据, 构造成 POST 请求, 交给后端服务器!
                let messageJson = {
                    "from" : from,
                    "to" : to,
                    "message" : message
                };
                $.ajax({
                type: 'post',
                contentType: 'application/json;charset=utf8',
                url: 'message',// 绝对路径的写法url: '/MessageWall/message',
                data: JSON.stringify(messageJson),
                success: function(body) {
                    alert("提交成功!");
                },
                error: function() {// 会在服务器返回的状态码不是 2xx 的时候触发这个 error. 
                    alert("提交失败!");
                }
            });
        }

        /*
        这个函数在页面加载时,从服务器获取到当前的消息列表
        并显示到页面上
        */
       function load(){
        $.ajax({
            type:'get',
            url:'message',
            success:function(body){
                /*
                此处得到的body是一个js对象的数组了
                本来服务器返回的是JSON格式的字符串,ajax会自动根据
                Content-Type对响应的body进行解析,解析成js对象
                */
               let container = document.querySelector('.container');
               for(let message of body){
                let newDiv = document.createElement('div');
                newDiv.className = 'row';
                newDiv.innerHTML = message.from + "对" + message.to + "说" +  message.message;
                container.appendChild(newDiv); 
               }
            }
        });
       }


       //函数调用写在这里,表示在页面加载时进行执行
       load();
        </script>
</body>
</html>

在这里插入图片描述
执行一下!!!

1.一开始加载页面 .

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.往服务器提交个数据 .
在这里插入图片描述
在这里插入图片描述

3.刷新页面 , 重新从服务器获取数据 .
在这里插入图片描述
在这里插入图片描述
此时已经从服务器获取到想要的数据了 , 不再是返回空列表了 .

过程解释 :

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接下来的问题是 , 当服务器从重启时 , List里的内容就会丢失 ! 如何解决这个问题呢 ?

  1. 存文件 , 使用IO流来读文件/写文件 .
  2. 数据库 , 使用MySQL + JDBC编程 .

此处我们让服务器把数据保存在MySQL服务器上 .

5.4将数据保存在MySQL服务器上

1.引入MySQL依赖 .

在这里插入图片描述

从中央仓库导入即可 .

  1. 创建数据库数据表 .

在这里插入图片描述

可以把上述操作写到一个单独的文件中 , 以备后用 .

在这里插入图片描述

  1. 调整后端代码 .
    a. 和数据库建立连接 , 单独搞一个DBUtil类 , 来实现数据库的建立连接 ;
    b. 封装数据库操作 , 通过JDBC来完成数据库的操作 .

DBUtil.java

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import javax.swing.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 期望通过这个类来完成数据库建立连接的过程
 * 建立连接需要使用DataSource,且一个程序有一个DDataSource实例即可.
 */
public class DBUtil {
    private static DataSource dataSource = null;
    private static DataSource getDataSource() throws SQLException {
        if(dataSource == null){
            dataSource = new MysqlDataSource();
            ((MysqlDataSource)dataSource).setURL("jdbc:mysql:://127.0.0.1:3306/MessageWall?characterEncoding=utf8&useSSL=false");
            ((MysqlDataSource)dataSource).setUser("root");
            ((MysqlDataSource)dataSource).setPassword("111111");
        }
        return dataSource;
    }
    public static Connection getConnection() throws SQLException{
        return getDataSource().getConnection();
    }

    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }


}

MessageServletl.java

import com.fasterxml.jackson.databind.ObjectMapper;

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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//对应前端传来的请求body
//保证这几个属性的名字都和json里的key对应
class Message{
    public String from;
    public String to;
    public String message;

    @Override
    public String toString() {
        return "Message{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    //private List<Message> messageList = new ArrayList<>();
    //负责实现让客户端提交数据给服务器
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.把body的json数据解析出来
        Message message = objectMapper.readValue(req.getInputStream(),Message.class);
        //2.把这个对象保存起来,最简单的方法,就是存到内存中.
        //messageList.add(message);
        save(message);
        System.out.println("message : " + message);
        //3.返回保存成功的响应
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write("{\"ok\" : 1}");
    }

    //负责实现让客户端从服务器拿到数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        //把对象转成json格式的字符串,此处messageList是一个List,直接被转成json数组
        List<Message> messageList = load();
        String respString = objectMapper.writeValueAsString(messageList);
        resp.getWriter().write(respString);
    }


    /**
     *  把当前的消息保存到数据库中
     *  */
    private void save(Message message){
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            //1.和数据库建立连接
           connection = DBUtil.getConnection();
            //2.构造SQL语句
            String sql = "insert into walldata values(?,?,?)";
            statement = connection.prepareStatement(sql);
            statement.setString(1,message.from);
            statement.setString(2,message.to);
            statement.setString(3,message.message);
            //3.执行SQL语句
            int ret = statement.executeUpdate();
            if(ret != 1){
                System.out.println("插入失败!");
            } else {
                System.out.println("插入成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //4.关闭连接
            DBUtil.close(connection,statement,null);
        }
    }

    /**
     * 从数据库查询到记录
     */
    private List<Message> load(){
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Message> messageList = new ArrayList<>();
        try {
            //1.建立连接
            connection = DBUtil.getConnection();
            //2.构造SQL
            String sql = "select * from walldata";
            statement = connection.prepareStatement(sql);
            //3.执行SQL
            resultSet = statement.executeQuery();
            //4.遍历结果集
            while(resultSet.next()){
                Message message = new Message();
                message.from = resultSet.getString("from");
                message.to = resultSet.getString("to");
                message.message = resultSet.getString("message");
                messageList.add(message);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5.释放资源
            DBUtil.close(connection,statement,resultSet);
        }
    return messageList;
    }
}

允许效果如下 :

在这里插入图片描述

此时查询数据库中的walldata表 , 已经保存了这条数据 !
在这里插入图片描述
再次刷新页面 :

在这里插入图片描述
内容任然存在 !

中断程序的运行 , 并再次启动 :

在这里插入图片描述

在这里插入图片描述

再次刷新页面 ,内容仍然存在 !

在这里插入图片描述

在这里插入图片描述

如果你发现结果不符合预期 , 怎么办 ?

起手式–抓包 !!!

1.一个是抓页面加载,看看GET /message方法请求和响应是啥样的 .

  1. 如果请求没问题,响应有问题,说明是后端问题 .
  2. 如果请求有问题,响应没问题,说明是前端问题.(检查发送ajax的代码)
  3. 如果请求响应都没问题,但是页面不能正确显示,还是前端问题~~(检查ajax的回调)

2.还可以再抓包POST看看有没有问题 .

3.还可以看看数据库里有没有正确数据.

如果数据库有数据,说明大概率是GET的时候出问题了.如果数据库没数据,说明大概率是POST的时候出问题了!!!

顺便记录一下笔者在这里出现的问题 :

1.没有加载jQuery .

在这里插入图片描述
2. 数据库密码写错了 .

在这里插入图片描述

你可能会问了 , 你这数据库密码不就泄露了吗 ?

我只能说 , 银行卡里没有余额,那掩盖密码也是无用的 .

六 : Cookie和Session

6.1 工作方式回顾

Cookie是浏览器给HTTP协议提供的一个持久化存储数据的方案.

在这里插入图片描述

典型应用 : 保存用户的身份信息 !

在这里插入图片描述
在这里插入图片描述

注意 : Cookie是在客户端存的 , Session是在服务器存的 , Sessionid是在客户端和服务器都存了 .

在这里插入图片描述

注意 : 实现登录和身份验证是Cookie的一种典型的应用 , 此时需要Cookie和Session搭配工作 , 其他场景则不一定需要搭配Session . Cookie里是可以存多个键值对的 , 具体存什么 , 是程序猿自己约定的 . 比如你想存登录的时间 , 就可以以LoginTime为key , 以登录的时间戳为value .

6.2 Servlet对Cookie和Session提供的API

6.2.1 HttpServletRequest 类中的相关方法

在这里插入图片描述

6.2.2 HttpServletResponse 类中的相关方法

在这里插入图片描述

6.2.3 HttpSession 类中的相关方法

一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息.

在这里插入图片描述

6.2.4 Cookie 类中的相关方法

每个 Cookie 对象是一个键值对

在这里插入图片描述

6.3 代码示例—实现用户登录

在这里插入图片描述

功能 : 登录页可输入用户名和密码 , 服务器验证正确性 . 如果正确跳转到主页 , 并在主页中显示出当前用户的身份信息 , 且显示出当前用户的登录的访问次数 . (当用户第一次登录成功后 , 就无须重新登录了) .

主页代码 : IndexServlet.java

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 javax.servlet.http.HttpSession;
import java.io.IOException;

//用这个Servlet返回主页信息
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession(false);
        if(session == null){
            //用户未登录,跳转到登录页面,要去用户重新登录
            resp.sendRedirect("login.html");
            return;
        }
        //已经成功登录
        String username = (String) session.getAttribute("username");
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        visitCount = visitCount + 1;
        session.setAttribute("visitCount",visitCount);

        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("当前用户为: " + username + "访问次数 :" + visitCount);
    }
}

登录页代码 LoginServlet.java

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 javax.servlet.http.HttpSession;
import java.io.IOException;

//用来处理登录请求
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        //读取请求中的参数,判定当前用户信息是否正确
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username == null || username.equals("") || password == null || password.equals("") ){
            //返回提示
            resp.getWriter().write("用户名或密码不完整!登录失败");
            return;
        }
        if(!username.equals("baizong") || !password.equals("123456")){
            resp.getWriter().write("用户名或密码错误!登录失败!");
            return;
        }
        //登录成功,创建一个会话,把用户信息填写到session里
        HttpSession session = req.getSession(true);
        session.setAttribute("username","baizong");
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        if(visitCount == null){
            session.setAttribute("visitCount",0);
        }
        resp.sendRedirect("index");

    }
}

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" value="提交">
    </form>
</body>
</html>

实现效果 :

在这里插入图片描述

存储结构 :

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七 : 上传文件

在这里插入图片描述

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

@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Part part = req.getPart("MyFile");
        //获取到文件的真实名字
        System.out.println(part.getSubmittedFileName());
        //获取文件大小
        System.out.println(part.getSize());
        //获取文件的类型
        System.out.println(part.getContentType());.
        //把文件写入服务器这边的磁盘中
         part.write("C:\\Users\\86177\\Desktop\\result.jpg");
        resp.getWriter().write("upload ok!");
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>upload</title>
</head>
<body>
    <form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="MyFile">
        <input type="submit" value="上传">
    </form>

</body>
</html>

在这里插入图片描述

最终效果 :

在这里插入图片描述

至此 , Servlet及其API全部介绍完毕 !

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐