15.Servlet

news2025/1/12 18:20:02

目录

1.Servlet的日常开发 

1.@WebServlet(...此处填写资源路径)

1.那么什么时候Tomcat会启动失败?

2.响应体是文本内容&&字符集编码是uft-8

 3.读取请求参数

4.资源的重定向(redirect)

2.面试问题:GET和POST有什么区别?

3.尝试写一个成绩单

1.错误处理(错误排查)

1.这里列举我遇到的:路径缺少404错误

2.开发者工具长期打开

3.具体每层可能出现的问题

4.  500错误

5.辅助方法

6.理清我们有多少资源,资源支持方法是什么,资源的Path是什么,资源的职责是什么,资源的关系

2.数据的持久化存储(文件 -> MySQL)

1.JDBC

3.拼接HTML比较麻烦(1.模板   2.前后端分离)

 类越来越多,为啥需要这么多类


1.Servlet的日常开发 

1.@WebServlet(...此处填写资源路径)

必须以 / 开头,并且路径不能重复

正常情况"/hello"   "/hello/world"

特殊情况:

(1)通配符"*.do"只要路径后缀名是 .do的都归我管

这是随便写的路径,路径结尾是.do,所以控制台打印了。

 (2)"/"  所有的URL都归它管

 随便写的任何路径都可以访问到,包括.do

有了这个再也不会出现404了

(3)" ",一个空格,这代表根目录URL

1.那么什么时候Tomcat会启动失败?

(1)端口被占用

(2)动态资源的绑定路径有错误的情况

2.响应体是文本内容&&字符集编码是uft-8

1.设置字符集编码

2.设置Content-Type的响应头

3.写响应体

不用调用setHeader(...),直接使用以下代码:

 3.读取请求参数

——读取网页中收集用户填写的信息

GET方法的参数放在query string中

POST方法的参数放在query string和request body中(备注:必须form提交的POST请求)

当GET请求时

1.请求参数放在URL中,格式是name = value&name=value

2.value是中文还是英文均可以在正常读取

3.如果只有name,没有value,读到的是一个空字符串

4.如果连Name都没有,读到的是null

当POST请求时

1.请求参数可以放在URL的query string中,也可以requery body中(必须提交form表单)

格式都是name=value&name=value

2.value是英文没问题,中文有问题,所以需要读取之前,设置请求的字符集编码(req.setCharacterEncording)

3.如果连name都没有,没有value,读到的是一个空的字符""

4.如果连name都没有,读到的是Null

所以,标准读取参数代码如下:

4.资源的重定向(redirect)

3XX + 响应头:Location

临时重定向有3个状态:

302Found   临时移动,未考虑保留

303See Other 不保留,退化成GET  

307Temporary Redirect 保留原方法  

302约等于307

2.面试问题:GET和POST有什么区别?

 根本区别只有一个,就是语义不同。GET代表获取的语义,POST代表的是提交语义。

具体表现上的不同:

1.标准中规定:GET不应该带有请求体;POST可以带有请求体。

2.有请求参数的话,GET请求放在查询字符串URL中,POST请求放在查询字符串或请求体中(form表单)

由于浏览器的实现,URL的长度限制(1000个字符)短于请求体的限制(无限制)

URL一般会记录在日志中,请求体不会记录日志,所以说,POST比FET稍微安全一些。

如果要真正安全,使用HTTP协议。

3.将HTTP方法类比成SQL动作

GET(select)、POST(insert)、PUT(update)、DELETE(delete)——Restful建议

GET、PUT是幂等的;GET无副作用,PUT有副作用(执行不会影响数据)

POST、DELETE不是幂等的

约束限制等级:无副作用>幂等。无副作用一定幂等,但幂等不一样是无副作用的。

    比如,select*from 表  where name= 'x';  今天、明天、永远执行下去,得到的结果都是一致的,这就是幂等的。反之,同样的语句,第一次成功,以后可能失败,就是不幂等的。


常见场景下的代码片段:

1.输出文本响应

 2.读取请求参数

 3.重定向redirect  (不保留方法的临时重定向  302/307) 

HTTP协议: 30X + Location 

redirect             vs          forword(...)

HTTP协议                     Servlet内部 


3.尝试写一个成绩单

在代码中录入了成绩,然后打印

@WebServlet("/demo-1")
public class Demo1 extends HttpServlet {
    //首先把数据准备好
    private final HashMap<String,Integer> 成绩单 = new LinkedHashMap<>();
    //linkedHashMap元素顺序与插入顺序保持严格一致
    // hashMap的元素保存顺序是随机的
    public void init() throws ServletException{
        成绩单.put("门门",99);
        成绩单.put("聪聪",88);
        成绩单.put("毛毛",78);
        成绩单.put("果果",80);
        成绩单.put("小平",60);
        //我只要直接在这里添加,就可以显示出来
        成绩单.put("嘻嘻",74);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        PrintWriter writer = resp.getWriter();
        //我们要输出完整的成绩单
        writer.println("<!DOCTYPE html>");
        writer.println("<html lang='zh-hans'>");
        writer.println("<head>");
        writer.println("   <meta charset='utf-8'>");
        writer.println("   <title>成绩单</title>");
        writer.println("</head>");
        writer.println("<body>");
        writer.println("   <table border='1'>");
        writer.println("        <tbody>");

        //这里要遍历成绩单

        for (Map.Entry<String, Integer> entry : 成绩单.entrySet()) {
            String name = entry.getKey();
            int grade = entry.getValue();
            writer.println("<tr>");
            writer.printf("<td>%s</td> <td>%d</td> ",name,grade);
            writer.println("</tr>");
        }
        writer.println("        </tbody>");

        writer.println("</table>");
//        writer.println("/<tbody>");
//        writer.println("/<body>");
//        writer.println("/<html>");

    }
}

具体拆分:

代码展示:

ListServlet类:

@WebServlet("/list.html")
//对web链接的引用可以具体到html/css文件的具体格式
public class ListServlet 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.println("<!DOCTYPE html>");
        writer.println("<html lang='zh-hans'>");
        writer.println("<head>");
        writer.println("   <meta charset='utf-8'>");
        writer.println("   <title>成绩单</title>");
        writer.println("</head>");
        writer.println("<body>");
        writer.println("   <table border='1'>");
        writer.println("        <tbody>");

        //这里要遍历成绩单

        for (Map.Entry<String, Integer> entry : GradeRepository.getInstance().map.entrySet()) {
            String name = entry.getKey();
            int grade = entry.getValue();
            writer.println("<tr>");
            writer.printf("<td>%s</td> <td>%d</td> ",name,grade);
            writer.println("</tr>");
        }
        writer.println("        </tbody>");

        writer.println("</table>");
    }
}

SaveServlet类:

@WebServlet("/save")
public class SaveServlet extends HttpServlet {
    public static HashMap<String,Integer> map = new HashMap<>();
    //这里必须定义成静态属性static,静态属性只有一份

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //需要做三件事
        //1.读取
        //2.保存
        //3.重定向
        
        //通过Post将数据保存
        req.setCharacterEncoding("utf-8");
        String name = req.getParameter("name");//获取参数
        String grade = req.getParameter("grade");
        //姓名和成绩不能为空
        if(name == null || name.trim().isEmpty()){
            System.out.println("姓名不能为空哟~");
            //走到这里,用户不按照操作,我们直接返回
            return;
        }
        if(grade == null || name.trim().isEmpty()){
            System.out.println("成绩不能为空哟~");
            return;
        }
                int g =0;
        try {
            g = Integer.parseInt(grade);
        }catch (NumberFormatException exc){
            System.out.println("输入的成绩不是数字哦~");
        }
        //2.保存: 保证数据是同一份数据
        //上一次我们使用了静态资源,这次使用一个新的方法
        GradeRepository.getInstance().map.put(name,g);

        //3.重定向
        resp.sendRedirect("/list.html");
    }
}

GradeRepository类:

  //成绩仓库
    //要让两个类实现资源共享,使用单例模式
public class GradeRepository {

    public final HashMap<String,Integer> map = new HashMap<>();
    //这里必须是public  ,否则save中无法访问

    private  final static GradeRepository repository = new GradeRepository();
    //这里必须static 才能保证同一份数据   单例模式
    protected static GradeRepository getInstance(){
        return repository;
    }
}

 record.html:

<body>
      <form method="post" action="/save">
          <input type="text" name="name">
          <input type="text" name="grade">
          <button>提交</button>
      </form>
</body>

 成绩录入功能{提交页面/列表页面} {/record.html      /save     /list.html}

红色资源是用户可以直接访问的

1.错误处理(错误排查)

1.这里列举我遇到的:路径缺少404错误

第一次我写的是/list,我以为会自动生成html文件,在浏览器中显示了404错误。

正确的写法:资源路径的引用应该具体到具体文件,比如js,或者html,这样才能查找到

2.开发者工具长期打开

看元素面板的内容是否正确,确保浏览器中的代码和IDEA中的代码是否一致

源码面板

网络面板

 查看当前资源的状态,具体可能出现什么错误

控制台

3.具体每层可能出现的问题

网络层(网络不通)

传输层(TCP链接无法建立:Tomcat没有启动、防火墙)

应用层(状态码)

Tomcat启动失败: 1.端口被占用  2.Servlet的URL问题  (开启了多个 或者 没有以/开头)

4.  500错误

@WebServlet("/will-500")
public class ThrowException extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        req.getParameter("username");
        req.getParameter("password");

        //int n = 1/0;
        //除零异常,一定会出现错误

        try{
            int n = 1/0;
        }catch(ArithmeticException e){
            throw new RuntimeException(e);
            //由于一个算法异常导致了运行时异常
        }
    }
}

(1)Tomcat内部的问题

(2)代码中出现了异常(观察异常发生的调用栈,找到代码出错的位置)

也可能是代码拼写错误,比如我遇到的,将数据库grades写成了grade,就一直报错

以上展示是专门写的500错误,我个人遇到的500错误,空指针异常,原因是DBUtil没有和数据库建议连接,我只写了return null。 

5.辅助方法

添加日志(添加打印)或者多去调试 

6.理清我们有多少资源,资源支持方法是什么,资源的Path是什么,资源的职责是什么,资源的关系

2.数据的持久化存储(文件 -> MySQL)

我们已经启动过Tomcat,并且录入了一定的数据。当我们再次重启Tomcat时,成绩单中的数据为空,这是为什么?

数据时保存在GradeRepository的hashMap中,重启Tomcat,就是上一个被暂停,开启了一个新的tomcat,这就是两个tomcat进程,进程和进程之间的数据是隔离的,所以新进程拿不到上一个进程的数据。

1.JDBC

需要引入一个jdbc-mysql的依赖

DataSource对象   Connection对象    PrepareStatement对象    executeUpdate/executeQuery

ResultSet对象    while(rs.next()){...//一行行的去读取}

关联数据库,还需要在pom.xml文件进行修改

显示如下,就说明导入成功

3.拼接HTML比较麻烦(1.模板   2.前后端分离)

主要是针对人的视角

前端通过ajax技术,从后端(通过HTTP协议)读取数据(数据格式JSON为主)

成绩录入——具体实现思路:

 类越来越多,为啥需要这么多类?

model包下是承载数据的具体的类,有时候也命名为DataObject DO

写这么多包,是为了方便程序员的阅读

1.承载数据的对象——属性  ( 鱼香肉丝)

   序列化:JSON、equals、comparable、hashCode

2.承载流程的对象——方法     (前台、服务员、厨师)

单例的


在不同文件格式下,相互转换用到的方法:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/19606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营三期 day 23 - 二叉树(9)

669. 修剪二叉搜索树 原文链接&#xff1a;669. 修剪二叉搜索树 题目链接&#xff1a;669. 修剪二叉搜索树 视频链接&#xff1a;669. 修剪二叉搜索树 在上图中我们发现结点 000 并不符合区间要求&#xff0c;那么将结点 000 的右孩子 结点 222 直接赋给 结点 333 的左孩子就…

Java设计模式 (1) —— Iterator迭代器模式

拿到这个话题&#xff0c;首先搞清楚&#xff1a;什么是迭代器&#xff1f; 大家都学过 for-i 循环&#xff0c;for-i循环的本质就是 通过i 或者 i-- &#xff0c;以实现 从数据的一端 一个一个地遍历数据元素&#xff0c;直到另一端的最后一个元素&#xff0c;将这里 i 的通用…

【Linux】基础IO —— 深入理解文件系统 | 软硬链接

&#x1f308;欢迎来到Linux专栏~~ 深入理解文件系统 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的…

安全需求和挑战

安全需求和挑战 从风险管理的角度讲&#xff0c;主要就是管理资产、威胁、脆弱性 和防护措施及其相关关系&#xff0c;最终保障云计算平台的持续安全&#xff0c;以及 其所支撑的业务的安全。 云计算平台是在传统 IT技术的基础上&#xff0c;增加了一个虚拟化 层&#xff0c;并…

大数据之——Hive

目录1. Hive 基本概念1.1 什么是 Hive1.2 Hive 的优缺点1.2.1 优点1.2.2 缺点1.3 Hive 架构原理2. Hive 安装2.1 Hive 安装地址2.2Hive 安装部署2.3MySQL 安装2.4 Hive 元数据配置到 MySQL2.4.1 拷贝驱动2.4.2 配置 Metastore 到 MySQL2.4.3 再次启动 Hive2.5 使用元数据服务的…

让学前端不再害怕英语单词(二)

写了本专栏的第一章让学前端不再害怕英语单词&#xff08;一&#xff09;后&#xff0c;反响热度还是比较高的&#xff0c;截止现在已经有20个收藏量了&#xff0c;所以趁热打铁来更第二章 第一章我们简单的介绍了html&#xff0c;css和js的部分高频单词&#xff0c;因为html要…

S32K144的GPIO使用

程序初始化前线使用Components工具对时钟和GPIO进行配置&#xff0c;然后再main函数里面初始化。 时钟配置参考&#xff1a; S32K144之时钟配置 - 明明1109 - 博客园 (cnblogs.com) gpio配置 S32K SDK使用详解之PinSettings组件配置与使用详解(S32K1xx PORT 和GPIO模块)_嵌…

jdk1.8新特性简介

一、引言 jdk1.8出来已经一段时间了&#xff0c;现在1.9也已经出来了&#xff0c;但是很多公司&#xff08;我们公司也一样&#xff09;不太愿意升级到高版本的jdk&#xff0c;主要是有老的项目要维护&#xff0c;还有升级的话配套的框架也要升级&#xff0c;要考虑的细节事情太…

实训素材纯HTML+CSS代码 (教育主题 3页 )

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 家乡旅游景点 | 家乡民生变化 | 介绍自己的家乡 | 我的家乡 | 家乡主题 | HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结…

SpringMVC具体工作流程(保姆教学)

目录 文章目录[toc]一、SpingMVC的常用组件二、[SpringMVC](https://so.csdn.net/so/search?qSpringMVC&spm1001.2101.3001.7020)的工作流程一、SpingMVC的常用组件 1&#xff09;DispatcherServlet 是一种前端控制器&#xff0c;由框架提供。 作用&#xff1a;统一处理请…

基于Simulink宽带单基地雷达系统仿真(附源码)

目录 一、探索示例 1.1 收发器 1.2 信号处理子系统 1.3 渠道 1.4 目标子系统 二、结果和显示 三、总结 四、程序 本示例演示如何仿真宽带雷达系统。当雷达系统的带宽超过系统中心频率的5%时&#xff0c;通常被认为是宽带的。对于此示例&#xff0c;将使用 10% 的带宽。 …

智慧供应链解决方案-最新全套文件

智慧供应链解决方案-最新全套文件一、建设背景二、建设思路三、建设方案智慧供应链具有以下特点1、高度智能化2、全流程数字化3、信息系统互联互通四、获取 - 智慧供应链全套最新解决方案合集一、建设背景 智慧供应链是结合物联网技术和现代供应链管理的理论、方法和技术&…

ES6 入门教程 16 Reflect 16.1 概述

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程16 Reflect16.1 概述16 Reflect 16.1 概述 Reflect对象与Proxy对象一样&#xff0c;也是 ES6 为了操作对象而提供的新 API…

nodejs校园二手交易管理系统vue

本系统的设计主要是为给网上用户提供购物方便&#xff0c;所以应该完成以下目标&#xff1a; (1) 登录、注册。用户要想在交易系统中购买商品&#xff0c;就必须先登录系统。如果不是会员&#xff0c;就必须先注册&#xff0c;然后才能登录系统。 (2) 查找商品。用户可以查找自…

求程序段中++x或者x++的频度,时间复杂度、执行次数

以下程序段中"x"的执行频度&#xff1f; 频度就是执行次数for i:1 to n then;for j:1 to n then;x;i1时 内圈for执行n次...in时 内圈执行n次我的理解&#xff1a;外圈for从1到n&#xff0c;有效循环是n次&#xff0c;外圈每循环一次&#xff0c;内圈循环n次&#…

C语言源代码系列-管理系统之学生籍贯信息

往期文章分享点击跳转>《导航贴》- Unity手册&#xff0c;系统实战学习点击跳转>《导航贴》- Android手册&#xff0c;重温移动开发 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过…

Python 3.11新功能:错误信息回溯

错误信息回溯 长按关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 扫码关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 Python 3.11于2022 年 10 月 24 日发布。这个最新版本的 Python 速度更快&#xff0c;对用户更友好…

QT源码拾贝0-5(qimage和qpainter)

目录 0 qt源码查看方法 1. qimage.cpp中线程池使用方法 2. qpainter_p.h中SmallStack模板元结构体存放智能指针 3. qpainter.cpp的保存函数&#xff0c;状态对象赋值使用std::exchange函数 4. qpainter.cpp中获得类对象的方法 5. qpainter.cpp中QChar字节操作&…

代码随想录算法训练营三期 day 22 - 二叉树(8)

235. 二叉搜索树的最近公共祖先 原文链接&#xff1a;235. 二叉搜索树的最近公共祖先 题目链接&#xff1a;235. 二叉搜索树的最近公共祖先 在 有序树 里: 从上向下递归遍历&#xff0c;第一次遇到 curcurcur 结点的数值在 p,qp, qp,q 结点对应数值的闭区间中&#xff0c;那么…

内网渗透神器CobaltStrike之Beacon详解(三)

Beacon的种类 HTTP Beacon和HTTPS Beacon 这两个beacon的原理是通过发送http请求与受害主机通信来传达命令, 以此实现控制效果 优点是传输数据快, 缺点时隐蔽性差, 容易被防火墙或内网审计工具拦截 TCP Beacon 自CS4.0版本之后只有反向的TCP Beacon可用, 基于TCP协议的通信…