Servlet_JSP

1.一些回顾

对于Tomcat部署中 我们有一些补充的点需要在此说明一下
1.如果我们想要查询MINEType的话 可以到TOMCAT_HOME/conf/web.xml中进行查询 里面记录了不同类型对应的MINEType
2.我们客户端发送请求数据给服务器之后 服务器会调用父类中的service方法 然后在内部决定调用doGet还是doPost方法 我们也可以重写service方法自定义service的内部逻辑

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/hello3/test" method="get"><div>账号 <input type="text" name="username"></div><div>密码 <input type="text" name="password"></div><div><button type="submit">登录</button></div>
</form>
</body>
</html>
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("/test")
public class TestServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(this + "_service");}
}

在这里插入图片描述
3.通过response获取的字符输出流PrintWriter不需要手动关闭 当service调用完毕以后就会自动关闭该输出流
4.alt+d启动tomcat之后的默认操作中 常用的有两个:update classes and resourses、redeploy 前者主要为针对只修改的servlet进行重新加载到项目的操作 而后者则为针对添加成员的servlet进行重新加载到项目的操作

2.Servlet

所谓Servlet 其实就是server(服务) applet(小程序)的简称 即小服务程序的意思
当一个请求数据发送到服务器之后 交由一个servlet处理 他会调用其中的service方法 然后在决定要调用doGet还是doPost方法

默认情况下 一个servlet类 只会被服务器创建一个实例对象 而且是发生在第一次处理客户端的请求数据时(不同的对象哈希值对应着不同的对象 我们可以通过对象哈希值的角度来验证一下这个结论)

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("/test")
public class TestServlet extends HttpServlet {public TestServlet(){System.out.println(this + "_构造方法");}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(this + "_service");}
}

以下是第一次发送数据以后的结果
在这里插入图片描述
接着我们修改了service的代码 然后重新加载到项目中 查看哈希值是否改变

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("/test")
public class TestServlet extends HttpServlet {public TestServlet(){System.out.println(this + "_构造方法");}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(this + "_service123");}
}

在这里插入图片描述
从结果中就可以看出 哈希值并没有改变 说明两次发送数据用的对象是同一个对象 而且对象创建的时机是在第一次接收客户端请求数据之时(我可以通过内存层面解释一下这个问题:修改代码修改的是代码区中的内容 而对象存放的位置是堆空间 修改代码区并不会影响堆空间的东西 既然对象没有发生改变 那么就一直沿用即可)
但是如果我们是为servlet类增删成员而通过redeploy的方式重新加载servlet类的话 那么每一次的redeploy中服务器都会销毁旧的servlet对象 同时创建出新的servlet对象 所以如果是每一次的redeploy的话 那么就会根据同一个servlet类创建出不同的对象

1.注意

有些人可能会这么想 就是既然服务器只会根据一个servlet类创建一个实例的话 那么该servlet类采用的就是单例模式 这种想法是错误的
我们先来看一下单例模式的实现

public class Person {// 构造方法私有化private Person(){}// 提供一个私有静态的对象 静态是为了确保程序运行过程中只有一份内存 私有则是为了不被外界访问private static Person instance = new Person();// 提供一个共有静态的获取实例方法 静态是为了保证通过类访问public static Person getInstance(){return instance;}
}
public class Main {public static void main(String[] args) {Person p1 = Person.getInstance();Person p2 = Person.getInstance();System.out.println(p1);// Person@1b6d3586System.out.println(p2);// Person@1b6d3586}
}

从结果证明 上述代码确实实现了一个单例模式 所谓单例模式就是根据一个类只能创建一个实例 我们就可以查看一下servlet类是否可以创建多个实例即可证明servlet类是否采用了单例模式

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("/test")
public class TestServlet extends HttpServlet {public TestServlet(){System.out.println(this + "_构造方法");// TestServlet@39ac9b6d_构造方法}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {TestServlet ts1 = new TestServlet();// TestServlet@2c4c84b_构造方法TestServlet ts2 = new TestServlet();// TestServlet@3282dd6a_构造方法System.out.println(ts1);// TestServlet@2c4c84bSystem.out.println(ts2);// TestServlet@3282dd6a}
}

从ts1和ts2打印的结果不同来看 就可以证明servlet并非采取单例模式 而是可以根据一个该类创建出多个实例

当然 你也可以为同一个servlet类起多个不同的别名

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({"/test1", "/test2"})
public class TestServlet extends HttpServlet {public TestServlet(){System.out.println(this + "_构造方法");// TestServlet@39ac9b6d_构造方法}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(this + "_service");}
}

这样 你可以通过不同的请求路径和服务器进行交互 并且如果只是修改代码重新加载的程度 服务器也只会创建一次servlet实例 而且时机为第一次接收请求数据的时候

还有一个需要注意的地方就是:不要在servlet中定义可写(可修改)的成员变量 这样会引发线程安全问题

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({"/test1", "/test2"})
public class TestServlet extends HttpServlet {private int age = 10;public TestServlet(){System.out.println(this + "_构造方法");// TestServlet@39ac9b6d_构造方法}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {age++;}
}

如果同时有多个请求数据发送给服务器的话 并且同时执行到age++;语句 假设同时发送两次 那么实际的结果11可能和预期结果12是不一致的 这就是所谓的线程安全问题 解决的方案就是将成员变量从可写改成可读 即声明为常量即可

还有一个值得注意的地方就是:http请求的默认端口号为80 如果你的tomcat服务器端口号设置为80的话 那么客户端发送请求过程中就可以省略端口号(会自动添加) 我们重新加载的方式选择restart server 这样才能保留端口号的修改
在这里插入图片描述

3.crm项目

所谓crm 就是customer relationship management的简称 即用户关系管理
我们想要实现的一个项目的效果其实就是当我们点击登录 如果登录成功 就会跳转到展示用户信息的页面 如果登录失败 就会提醒我们重新登陆 并且点击可以实现跳转到登录界面的效果
而且在servlet代码中 我们需要单独封装登录成功、登录失败以及获取储存用户信息的功能
并且我们可以直接创建一个servlet类 而并非class类 该类已经有了基本的框架 包含doGet、doPost以及WebServlet等信息
我们接下来就来实现一下该项目
LoginServlet

package com.mj.servlet;import com.mj.bean.Customer;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.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;@WebServlet("/login")
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 设置请求数据的解码方式为UTF-8request.setCharacterEncoding("UTF-8");// 接收请求参数String username = request.getParameter("username");String password = request.getParameter("password");// 然后设置响应数据的内容格式 由于展示的为html页面 因此MINEType为text/html 而编码方式设置为UTF-8response.setContentType("text/html;charset=utf-8");// 然后定义字符输出流 用于输出响应数据PrintWriter out = response.getWriter();// 判断 如果登录成功 执行登录成功的逻辑 登陆失败则执行登录失败的逻辑if(username.equals("123") && password.equals("123")){success(out);}else{fail(out);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}// 封装获取储存用户信息的逻辑private List<Customer> getCustomers(){// 定义一个list集合 用于存放用户信息List<Customer> customers = new ArrayList<>();// 假设我们拥有的用户信息数量为10个for(int i = 0; i < 10; ++i){// 性别奇数为男 偶数为女customers.add(new Customer("张三", "10086", ((i & 1) == 1 ? "男" : "女")));}return customers;}// 封装登录成功的逻辑private void success(PrintWriter out){// 先展示登录成功信息out.write("<h1>登录成功</h1>");out.write("<table>");out.write("<thead>");out.write("<tr>");out.write("<th>姓名</th>");out.write("<th>电话</th>");out.write("<th>年龄</th>");out.write("</tr>");out.write("</thead>");out.write("<tbody>");// 获取存放用户信息的列表List<Customer> customers = getCustomers();for(Customer customer: customers){out.write("<tr>");out.write("<td>" + customer.getName() + "</td>");out.write("<td>" + customer.getPhone() + "</td>");out.write("<td>" + customer.getGender() + "</td>");out.write("</tr>");}out.write("</tbody>");out.write("</table>");}// 封装登录失败的逻辑private void fail(PrintWriter out){// 先展示登录失败信息out.write("<h1>登录失败</h1>");// 在展示重新登录 并且跳转到登录界面out.write("<a href=\"http://localhost:8080/crm/login.html\">重新登录</a>");}
}

Customer

package com.mj.bean;public class Customer {// 定义三个私有成员变量 分别为:姓名、电话以及性别private String name;private String phone;private String gender;// 定义无参和有参的构造方法public Customer(String name, String phone, String gender) {this.name = name;this.phone = phone;this.gender = gender;}public Customer() {}// 定义每一个成员变量的getter和setter方法public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}
}

login

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/crm/login" method="post"><div>账号 <input type="text" name="username"></div><div>密码 <input type="text" name="password"></div><div><button type="submit">登录</button></div>
</form>
</body>
</html>

文件架构
在这里插入图片描述
测试之后 可以发现 确实能够满足我们的需求 但是如果要将网页作为响应数据返回给客户端的话 那么就会出现大量可读性极差、难以维护的字符串拼接代码 而且我们的用户信息都是我们自己写死的(一般的解决思路就是将他们放置在数据库中)

4.Servlet处理请求的常见过程

在这里插入图片描述

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

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

相关文章

CMakeLists.txt语法规则:while 循环

一. 简介 前面几篇文章学习了 CMakeLists.txt语法中的一种循环写法&#xff0c;文章如下&#xff1a; CMakeLists.txt语法规则&#xff1a;foreach 循环基本用法-CSDN博客 CMakeLists.txt语法规则&#xff1a;foreach循环的关键字-CSDN博客 本文学习 while循环写法。 二. …

Day08-JavaWeb开发-MySQL(多表查询内外连接子查询事务索引)Mybatis入门

1. MySQL多表查询 1.1 概述 1.2 内连接 -- 内连接 -- A. 查询员工的姓名, 及所属的部门名称(隐式内连接实现) select tb_emp.name, tb_dept.name from tb_emp,tb_dept where tb_emp.dept_id tb_dept.id;-- 起别名 select * from tb_emp e, tb_dept d where e.dept_id d.id…

tomcat+maven+java+mysql图书管理系统2-完善项目结构,添加相关依赖

1.创建java目录 接着选择java&#xff0c;回车&#xff0c;则创建成功&#xff0c;成功后在左侧栏能看见 2.修改pom.xml文件,(添加依赖) <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

Thinkphp5 实现 redis 数据缓存

在ThinkPHP 5中&#xff0c;你可以使用Redis作为数据缓存的解决方案。Redis是一个开源的内存数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中介。下面是在ThinkPHP 5中实现Redis数据缓存的基本步骤&#xff1a; 1. 安装 Redis 扩展 首先&#xff0c;你需要在你的…

vs 2022 Xamarin 生成 Android apk

再保存&#xff0c;如果没有生成apk就重启软件 再试一次

Windows内核开发:如何使用STL

前言 大家都知道应用层c的STL非常强大&#xff0c;非常好用&#xff0c;但是在内核下就没法用了。针对这个问题&#xff0c;经过我不懈的寻找&#xff0c;终于找到了解决内核无法使用STL的方法。 使用new/delete关键字 先说一下常用关键字如何在内核中使用。其实只需要在一个全…

广西壮族自治区工程系列住房城乡建设行业高、中、初级职称评审条件

广西壮族自治区工程系列住房城乡建设行业高、中、初级职称评审条件评审文件链接广西壮族自治区人力资源和社会保障厅网站评审工作的通知广西壮族自治区人力资源和社会保障厅网站类别基本条件学术成果备注工程师&#xff08;一&#xff09;具备博士学位&#xff1b;或具备硕士学…

上位机开发PyQt5(三)【布局、单选框和多选框、对话框】

目录 一、布局Layout 1. 布局简介 2. 水平布局QHBoxLayout 3. 竖直布局QVBoxLayout 4. 表单布局QFormLayout 5. 布局嵌套 二、单选框和复选框 1. 单选框 2. 复选框 三、对话框 1. QMessageBox 2. QIputDialog 一、布局Layout 1. 布局简介 一个pyqt窗口中可以有多…

百度文库可直接下载VIP文章

百度文库文件下载 百度文库是百度公司推出的一款在线文档分享平台&#xff0c;它可以让用户免费上传、分享、下载和浏览各类文档资源&#xff0c;包括但不限于文章、论文、报告、PPT、书籍等。 好了&#xff0c;废话不多说&#xff0c;这里推出的新生产的软件&#xff0c;可直…

机器学习的指标评价

之前在学校的小发明制作中&#xff0c;在终期答辩的时候&#xff0c;虽然整个项目的流程都答的很流畅。 在老师提问的过程中&#xff0c;当老师问我recall,precision,accuracy等指标是如何计算的&#xff0c;又能够表示模型的哪方面指标做得好。我听到这个问题的时候&#xff…

内存映射文件

内存映射文件(Memory-Mapped Files)是一种在Windows和其他操作系统中使用的技术,它允许应用程序将文件的内容映射到进程的地址空间中,这样文件就可以像内存一样被直接访问,而无需进行传统的文件读/写操作。这种技术可以提高文件访问的性能,因为内存访问通常比磁盘I/O操作…

图片倾斜矫正处理(Hough Transform)

目录 倾斜矫正原理及实现方式Canny边缘检测非极大值抑制霍夫变换 倾斜矫正原理及实现方式 代码连接&#xff1a;https://github.com/shuyeah2356/Image-Angel-correction/tree/main 倾斜矫正的实现原理&#xff1a; 使用霍夫变换检测图片中的直线&#xff1b; 计算直线与水平方…

【与 Apollo 共创生态:展望自动驾驶全新未来】

1、引言 历经七年的不懈追求与创新&#xff0c;Apollo开放平台已陆续推出了13个版本&#xff0c;汇聚了来自全球170多个国家与地区的16万名开发者及220多家合作伙伴。随着Apollo开放平台的不断创新与发展&#xff0c;Apollo在2024年4月19日迎来了Apollo开放平台的七周年大会&a…

周末总结(2024/05/05)

工作 人际关系核心原则&#xff1a; 要学会随时回应别人的善意。 人际关系的本质是价值交换&#xff08;利益和情绪&#xff09; 接受破烂现状&#xff0c;改变状态 - 这周写了两天代码&#xff0c;总结了node.js的面试题&#xff0c;其他时间都在摸鱼&#xff0c;状态很差&am…

猿人学第七题-动态字体-随风漂移

前言&#xff1a;该题主要是考对fontTools.ttLib.TTFont的操作&#xff0c;另外就是对字典互相映射的操作 一、woff文件存储 from fontTools.ttLib import TTFont #pip install fontTools def save_woff(response):woff response[woff]woff_file base64.b64decode(woff.enc…

.排序总讲.

在这里赘叙一下我对y总前四节所讲排序的分治思想以及递归的深度理解。 就以788.逆序对 这一题来讲&#xff08;我认为这一题对于分治和递归的思想体现的淋淋尽致&#xff09;。 题目&#xff1a; 给定一个长度为 n&#x1d45b; 的整数数列&#xff0c;请你计算数列中的逆序对…

Linux的软件包管理器-yum

文章目录 软件包的概念yum源的配置的原因yum的使用查看软件包安装软件卸载软件 软件包的概念 软件包(SoftWare Package)是指具有特定的功能&#xff0c;用来完成特定任务的一个程序或一组程序。可分为应用软件包和系统软件包两大类 在Linux系统中&#xff0c;下载安装软件的方式…

力扣:100284. 有效单词(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 有效单词 需要满足以下几个条件&#xff1a; 至少 包含 3 个字符。 由数字 0-9 和英文大小写字母组成。&#xff08;不必包含所有这类字符。&#xff09; 至少 包含一个 …

leetcode_46.全排列

46. 全排列 题目描述&#xff1a;给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#…

Java学习之集合2

集合&#xff1a; 1.ArrayList集合类 import java.util.ArrayList;public class Demo01ArrayList {public static void main(String[] args) {/*ArrayList类概述底层数据结构是数组&#xff0c;查询快&#xff0c;增删慢TODO 方法插入数据时不会对插入的数据进行自然排序或字…