JavaWeb基础学习
WebWeb软件架构1. 客户端(前端)2. 服务器端(后端)3. 服务层4. 数据层5. 安全层6. 缓存层7. 监控和日志8. 构建和部署9. 架构模式
Web 服务器Servlet快速入门:Servlet3.0前端跳转ServletServlet相关配置
HTTP协议HTTP协议分层模型HTTP的基本特点请求(Request)与响应(Response)Request体系结构request 功能获取请求行数据获取请求头数据获取请求体数据获取请求参数请求转发共享数据获取 `ServletContext`
Response响应消息重定向`forward` 和 `redirect` 区别
Web
Java Web 开发是指使用 Java 技术构建动态的 Web 应用程序。它涉及到多个层次的开发,包括前端展示、业务逻辑处理和数据持久化。
Web软件架构
Web 软件架构涉及设计和组织 Web 应用程序的不同组件和层次,以确保系统的可维护性、扩展性和性能。以下是常见的 Web 软件架构组件和模式:
1. 客户端(前端)
用户界面(UI):包括网页设计和用户交互元素,通常使用 HTML、CSS 和 JavaScript 开发。前端框架:如 React、Angular、Vue.js,用于构建动态和响应式用户界面。客户端逻辑:处理用户输入、验证、动态更新页面内容等功能。
2. 服务器端(后端)
应用服务器:处理业务逻辑和数据处理,接收客户端请求并生成响应。常见的应用服务器包括 Apache Tomcat、Jetty、JBoss 等。Web 服务器:如 Apache HTTP Server、Nginx,负责接收客户端请求并将其转发给应用服务器。
3. 服务层
业务逻辑:处理应用程序的核心功能,如数据处理、计算和业务规则。服务接口:提供与客户端或其他服务交互的 API 接口,通常使用 RESTful API 或 GraphQL。
4. 数据层
数据库:存储和管理应用程序的数据。包括关系型数据库(如 MySQL、PostgreSQL)和 NoSQL 数据库(如 MongoDB、Cassandra)。数据访问层:负责与数据库的交互,进行数据的增删改查操作。通常使用 ORM(对象关系映射)工具,如 Hibernate、JPA。
5. 安全层
身份验证:验证用户的身份,确保用户是其声称的身份。常见的方法包括用户名/密码、OAuth、JWT(JSON Web Token)。授权:管理用户的权限,控制用户对特定资源的访问权限。数据加密:保护数据的机密性,使用 SSL/TLS 加密数据传输。
6. 缓存层
缓存:提高系统性能,减少数据库访问次数。常见缓存工具包括 Redis、Memcached。内容分发网络(CDN):加速静态资源的分发,提高网站的加载速度,减少服务器负担。
7. 监控和日志
监控:实时监控应用程序和服务器的性能,检测系统健康状况。工具如 Prometheus、Grafana。日志:记录应用程序的运行状态和错误信息,用于故障排查和性能分析。工具如 ELK Stack(Elasticsearch, Logstash, Kibana)。
8. 构建和部署
构建工具:自动化编译、测试和打包过程,如 Maven、Gradle。持续集成/持续部署(CI/CD):自动化构建、测试和部署应用程序,提高开发效率和代码质量。容器化:使用 Docker 容器技术部署应用程序,确保环境一致性和便于扩展。
9. 架构模式
MVC(Model-View-Controller):将应用程序分为模型、视图和控制器三部分,分离业务逻辑和用户界面。微服务架构:将应用程序拆分为多个独立的服务,每个服务负责不同的功能,彼此通过 API 进行通信。单体架构:将应用程序的所有功能打包在一个单一的部署单元中,适用于小型应用程序或初期开发阶段。
Web 服务器
我们在学习与测试中,通常会使用TomCat来作为小型的Web服务器,Tomcat 是一个开源的 Servlet 容器,负责运行 Java Servlets 和 JSP(JavaServer Pages)。它实现了 Java EE(现在称为 Jakarta EE)规范中的 Servlet 和 JSP 部分,使得 Java Web 应用程序可以在其中运行。
这里便产生了一个问题,什么是Servlet? Servlet 是 Java EE(现在称为 Jakarta EE)规范的一部分,用于创建动态 Web 应用程序的服务器端组件。它是一种 Java 类,通过实现 javax.servlet.Servlet 接口,处理客户端请求并生成响应。
通俗来讲,Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。 那么,我们应该学习他有哪些用法:
Servlet快速入门:
创建JavaEE项目
导入依赖
定义一个类,实现Servlet接口
public class ServletDemo1 extends HttpServlet
实现抽象类中的抽象方法
在web.xml中配置:
代码示例:
public class ServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("doPost");
}
}
Servlet3.0
好处:
支持注解配置。可以不需要配置web.xml了
步骤:
创建JavaEE项目定义一个类,实现Servlet接口重写方法在类上使用@WebServlet注解,进行配置
代码示例:
@WebServlet(urlPatterns = "/demo1")
@WebServlet(value = "/demo2")
@WebServlet(name = "/demo3")
@WebServlet("/demo4")
前端跳转Servlet
@WebServlet("/servlet4")
public class Servlet4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("doPost");
}
}
Servlet相关配置
urlpartten:Servlet访问路径
一个Servlet可以定义多个访问路径 : @WebServlet({“/d4”,“/dd4”,“/ddd4”}) 路径定义规则:
/xxx:路径匹配/xxx/xxx:多层路径,目录结构*.do: 扩展名匹配
代码示例:
@WebServlet({"/d2", "/dd2", "/ddd2"})//都可以访问到
@WebServlet("/demo2/user") //多层路径
@WebServlet("/demo2/*") //通配符, *任意字符
@WebServlet("*.do") // 任意字符.do 访问
HTTP协议
HTTP(HyperText Transfer Protocol)是一种用于在客户端(如浏览器)和服务器之间传输数据的协议。它是Web通信的基础,主要用于请求和响应的交换。
HTTP协议分层模型
图片转载自:互联网协议 - 走看看
HTTP 协议可以从不同的层次进行分解和理解,但通常不直接划分为多层。我们可以从网络协议的层次结构和 HTTP 协议的设计角度来理解它的分层:
应用层
HTTP协议本身:在OSI模型和TCP/IP模型中,HTTP 处于应用层。它定义了客户端和服务器之间的数据交换格式,包括请求和响应的结构、方法、状态码、头信息等。HTTP的请求和响应:包括 HTTP 请求方法(如 GET、POST)、状态码(如 200 OK、404 Not Found)、头信息(如 Content-Type、Authorization)和正文(body)等。
传输层
TCP:在实际的数据传输中,HTTP 协议通常运行在 TCP 协议之上。TCP 提供了可靠的、面向连接的传输服务,确保 HTTP 消息的正确传输。TLS/SSL:当 HTTP 被加密(使用 HTTPS)时,SSL/TLS 协议在传输层提供加密和安全保障。
网络层
IP:HTTP 数据包在网络中传输时,IP 协议负责将数据从源地址传输到目标地址。IP 协议位于网络层,提供了数据包的寻址和路由功能。
数据链路层
以太网/Wi-Fi等:在最底层,数据链路层协议负责在物理网络上传输数据帧,包括以太网、Wi-Fi等技术。
HTTP的基本特点
请求-响应模型:
客户端请求:客户端(如浏览器)发起HTTP请求,向服务器请求资源或服务。服务器响应:服务器处理请求并返回HTTP响应,包含请求结果或错误信息。
无状态:
每个请求都是独立的,与之前或之后的请求无关。服务器不会记住客户端的状态或会话信息。
方法:
GET:请求资源,通常用于获取数据。POST:提交数据,通常用于提交表单数据或创建资源。PUT:更新资源,用于替换指定资源的内容。DELETE:删除资源,用于请求删除指定资源。HEAD:类似于GET,但只请求头信息,不返回实际数据。OPTIONS:请求支持的HTTP方法。
状态码:
2xx:成功(如200 OK)。3xx:重定向(如301 Moved Permanently)。4xx:客户端错误(如404 Not Found)。5xx:服务器错误(如500 Internal Server Error)。
头信息:
HTTP头信息包含请求和响应的元数据,如Content-Type、Content-Length、User-Agent等,用于描述数据的格式、长度和客户端信息。
协议版本:
HTTP/1.0:较早的版本,支持基础功能。HTTP/1.1:引入了持久连接和管道化等功能,提升了性能。HTTP/2:改进了性能,支持多路复用和压缩头信息,减少了延迟。HTTP/3:基于QUIC协议,进一步减少延迟并提升性能。
请求(Request)与响应(Response)
理解 HTTP 中的请求与响应是掌握 Web 通信的基础。HTTP 请求和响应是客户端(如浏览器)与服务器之间交换信息的方式。以下是对 HTTP 请求和响应的详细理解:
Request
体系结构
HttpServletRequest 继承自 ServletRequest 接口。
ServletRequest -- 父接口
⬆️
HttpServletRequest -- 子接口
request 功能
获取请求行数据
请求行示例:GET /day02/demo1?name=zhangsan HTTP/1.1
1. 获取请求方式:GET
* String getMethod()
2. 获取虚拟目录:/day02
* String getContextPath()
3. 获取 Servlet 资源路径:/demo1
* String getServletPath()
4. 获取 GET 请求参数:name=zhangsan
* String getQueryString()
5. 获取请求 URI:/day02/demo1
* String getRequestURI()
* StringBuffer getRequestURL() // http://localhost/day02/demo1
6. 获取协议及版本:HTTP/1.1
* String getProtocol()
代码示例:
System.out.println(req.getMethod()); // GET/POST
System.out.println(req.getContextPath()); // /day02
System.out.println(req.getServletPath()); // /demo1
System.out.println(req.getQueryString()); // name=zhangsan
System.out.println(req.getRequestURI()); // /day02/demo1
System.out.println(req.getRequestURL()); // http://localhost:8080/day02/demo1
System.out.println(req.getProtocol()); // HTTP/1.1
获取请求头数据
方法:
String getHeader(String name):获取请求头的值Enumeration
代码示例:
Enumeration
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name + "-----" + value);
}
获取浏览器信息:
String agent = req.getHeader("user-agent");
if (agent.contains("Chrome")) {
System.out.println("谷歌浏览器");
} else if (agent.contains("Firefox")) {
System.out.println("火狐浏览器");
}
获取请求体数据
请求体仅在 POST 请求中存在。
步骤:
获取流对象:
BufferedReader getReader():获取字符输入流
代码示例:
HTML 表单:
Servlet 代码:
@WebServlet("/requestDemo04")
public class RequestDemo04 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
获取请求参数
通用方法:
String getParameter(String name):获取参数值String[] getParameterValues(String name):获取参数值的数组
注意:
对于 POST 请求,设置编码为 UTF-8 以避免中文乱码:request.setCharacterEncoding("utf-8");
代码示例:
HTML 表单:
Servlet 代码:
@WebServlet("/requestDemo05")
public class RequestDemo05 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("请求参数:" + username);
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
}
请求转发
服务器内部的资源跳转。
步骤:
获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String path) 使用 RequestDispatcher 对象进行转发:
forward(ServletRequest request, ServletResponse response)
代码示例:
@WebServlet("/requestDemo06")
public class RequestDemo06 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dis = request.getRequestDispatcher("/request2");
dis.forward(request, response);
}
}
共享数据
request 域:请求范围内的数据共享。
void setAttribute(String name, Object obj):存储数据Object getAttribute(String name):获取数据void removeAttribute(String name):移除数据
代码示例:
Servlet 1:
@WebServlet("/requestDemo08")
public class RequestDemo08 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("msg", "我是RequestDemo08的资源");
RequestDispatcher dis = request.getRequestDispatcher("/requestDemo09");
dis.forward(request, response);
}
}
Servlet 2:
@WebServlet("/requestDemo09")
public class RequestDemo09 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Object msg = request.getAttribute("msg");
System.out.println("我访问到的资源是:" + msg);
}
}
获取 ServletContext
ServletContext 是一个全局存储空间,所有用户都可以访问。
方法:
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name", "zhangsan");
代码示例:
Servlet 1:
@WebServlet("/request1")
public class Request1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext sc = request.getServletContext();
sc.setAttribute("msg", "hello1");
request.getRequestDispatcher("/request2").forward(request, response);
}
}
Servlet 2:
@WebServlet("/request2")
public class Request2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext sc = request.getServletContext();
System.out.println("msg = " + sc.getAttribute("msg"));
}
}
Response
响应消息
响应行:包括协议/版本、响应状态码、状态码描述
例如:HTTP/1.1 200 OK 响应头:
格式:头名称: 值示例:Content-Type: text/html;charset=UTF-8 响应空行
响应体:传输给客户端的数据
响应体示例:
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Thu, 17 Sep 2020 02:59:05 GMT
Location: /servletB
我是response
重定向
重定向:资源跳转的方式
设置状态码为 302设置响应头 Location
代码示例:
@WebServlet("/responseServlet01")
public class ResponseServlet01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("/Day03/responseServlet02");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/responseServlet02")
public class ResponseServlet02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("responseServlet02");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
}
forward 和 redirect 区别
重定向 (redirect):
地址栏发生变化可以访问其它站点资源两次请求,不能使用 request 对象共享数据 转发 (forward):
地址栏路径不变只能访问当前服务器资源一次请求,可以使用 request 对象共享数据
注意: 不能使用重定向来访问 request 域中的数据。