【JavaWeb】JavaWeb 基础
JavaWeb
JavaWeb是指所有通过Java语言编写的,可以通过浏览器访问的程序的总称。JavaWeb是基于请求和响应开发的。
- 请求:客户端给服务器发送数据,Request
- 响应:服务器给客户端传回数据,Response
JavaWeb三大组件:Servlet程序、Filter过滤器、Listener监听器
HTTP
HTTP:超文本传输协议。是一个简单的请求-响应协议,通常运行在TCP之上,端口号:80。HTTPS相比HTTP更为安全。HTTP两个时代:
- HTTP1.0:客户端与web服务器连接后,只能获得一个web资源。
- HTTP2.0:客户端与web服务器连接后,可以获得多个web资源。
HTTP 请求
请求行:
- 请求行中的请求方式:
GET
或POST
- 请求方式:
GET
、POST
、HEAD
、DELETE
、PUT
GET
:检索 && 获取。会在 URL 中显示数据内容(URL 长度有限制,视浏览器而定,例如Chrome的URL长度限制为2Mb,2048个字符),一般没有请求体。不安全,但高效。是幂等性的。Content-Type
通常为application/x-www-form-urlencoded
POST
:创建 || 更新。不会在URL中显示数据内容,而是显示在请求体中。相对安全,但不高效。请求对资源有副作用,不是幂等性的。
HTTP POST 请求的内容是在请求体内的,但也不是绝对安全的。他人截获该请求后仍可以得到请求体内容。若想保证安全性,还需要使用 HTTPS 的加密方法对请求体内容进行加密。
GET请求
中文在URL中使用百分号编码(Percent-Encoding,只是一种机制),字符的编码方式通常是UTF-8,而不是使用ASCII编码。
POST请求
浏览器的收藏和前进跳转都是 GET 请求,因为 GET 请求会在 URL 中保存具体参数,而 POST 一般不会保存。GET 请求常用来做缓存,POST 请求一般不做缓存。
GET 请求用于缓存:
HTTP 响应
响应状态码:
- 101:转换协议(例如HTTP协议转换成WebSocket协议)
- 200:请求响应成功
- 3xx:请求与重定向(304可以使用缓存的内容)
- 4xx:找不到资源(404 资源不存在),客户端的错误(比如输入错误的地址),访问被拒绝(403 Forbidden 权限不够)
- 5xx:服务器内部错误(500),网关错误(502)
URL 和 URI
URI:资源识别符;URL:比 URI 多了一个定位功能,就是用定位的方式实现的 URI。URL 是 URI 的子集。
- 在 Web 领域上,假设所有的 Html 文档都有唯一的编号,记作 html:xxxxx,xxxxx 是一串数字,即Html 文档的身份证号码,这个能唯一标识一个 Html 文档,那么这个号码就是一个 URI。
- 而 URL 则通过描述是哪个主机上哪个路径上的文件来唯一确定一个资源,也就是定位的方式来实现的 URI。
示例:
- URL:http://yunmall.com/order/saveOrder(需要带上服务器信息、协议信息等)
- URI:
/order/saveOrder
Tomcat
Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全局管理和Tomcat阀等。由于Tomcat本身也内含了HTTP服务器,因此也可以视作单独的Web服务器。Tomcat提供了一个Jasper编译器用以将JSP编译成对应的Servlet。
在官网安装Tomcat 9.0.45版本压缩包,解压到本地即可,无需配置环境变量。在构建Servlet项目时,在IDEA中指定Tomcat根目录即可使用Tomcat。
Maven
Maven 项目架构管理工具
用于方便导入jar包。核心思想:约定大于配置。有约束,不要去违反。Maven会规定好如何去编写Java代码,必须按照这个规范组织结构。
修改为Maven阿里云镜像:
1 | <mirror> |
修改本地仓库的位置:localRepository
1 | <localRepository>D:\Environment\apache-maven-3.8.1\maven-repo</localRepository> |
Maven 仓库
Maven repository:https://mvnrepository.com/
Maven 约定
创建JavaWeb项目时,webapp目录创建在src/main目录下才能够自动导入maven配置文件中添加的包,否则需要在项目结构中手动导入包。
Servlet
Servlet是Sun公司开发动态web的一门技术。Sun在这些API中提供了一个接口:Servlet。开发Servlet程序需要完成两个步骤:
- 编写一个Java类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
把实现了Servlet接口的Java程序叫做Servlet
HelloServlet
Sevlet接口Sun公司提供有两个默认的实现类:HttpServlt,GenericServlet
- 构建一个普通的Maven项目(不带模板),删掉里面的src目录,这个空的工程就是Maven的主工程。之后在这个项目里建立Module,新建的Module均为Maven父项目的子项目。
- 关于Maven父子工程的理解:父项目中的Maven依赖环境Jar包子项目可以直接使用
1 | <modules> |
- Maven环境优化:修改web.xml(与本地Tomcat中的内容一致)
1 | <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" |
- 编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口,这里继承HttpServlet
1 | package com.zhao.servlet; |
- 编写Servlet映射:写的Java程序要通过浏览器访问,浏览器需要连接web服务器,所以需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能访问到的路径。
1 | <!-- 注册Servlet --> |
- 配置Tomcat,注意配置项目发布的路径
- 启动测试
Servlet 原理
Servlet是由web服务器调用,web服务器在收到浏览器请求后会调用service()
方法,该方法会根据请求的类型GET
或POST
分发处理,执行相应的doGet()
或doPost()
方法。
Mapping 问题
- 一个Servlet可以指定一个映射路径
1 | <servlet-mapping> |
- 一个Servlet可以指定多个映射路径
1 | <servlet-mapping> |
- 一个Servlet可以指定通用映射路径
1 | <servlet-mapping> |
- 默认请求路径
1 | <servlet-mapping> |
优先级问题:
指定了固有的映射路径优先级最高,如果找不到匹配的固有映射路径,则就会走默认路径(*)
1 | <!-- 注册Error Servlet --> |
ServletContext
是一个接口,代表Servlet上下文对象,一个工程只有一个ServletContext对象,是一个域对象(这里的域指的是整个web工程)。
web容器在启动时,他会为每个web程序都创建一个ServletContext对象,他代表了当前的web应用。
作用1:共享数据,即在某个Servlet中保存的数据可以在另一个Servlet中获得。
存入数据的Servlet类,用于保存数据到ServletContext对象中。
1 | public class HelloServlet extends HttpServlet { |
读入数据的Servlet类,用于从ServletContext对象中读取数据。
1 | public class GetServlet extends HttpServlet { |
作用2:获取初始化参数。
1 | <!-- 是上下文参数(属于整个web工程) --> |
1 | ServletContext context = this.getServletContext(); |
作用3:请求转发。
访问当前url时,将消息转发给指定的其他url(当前url不会发生变化,重定向会变化)。当前url只充当转发功能。请求转发不需要添加项目名,只需要/+映射路径
1 | // 转发的请求参数 |
请求转发的特点:
- 浏览器地址栏没有变化
- 是一次请求
- 共享Request域中的数据
- 可以转发到
WEB-INF
目录下 - 无法访问项目以外的其他资源(如百度)
作用4:读取资源文件
- 在java目录下新建properties
- 在resources目录下新建properties
发现都被打包到了同一个路径下:/WEB-INF/classes
,将这个路径称为classpath。
classpath:src/main/
下的java
目录和resources
目录下的文件会被合并到/WEB-INF/classes
下,将该路径称为classpath
1 | username=root |
1 | InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); |
HttpServletResponse
web服务器接收到客户端的HTTP请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse对象。
- 如果要获取客户端请求过来的参数,使用HttpServletRequest
- 如果要给客户端响应一些信息,使用HttpServletResponse
负责向浏览器发送数据的方法:
getOutputStream()
getWriter()
常见应用:
- 向浏览器输出消息
- 下载文件
1 | // 设置让浏览器能够支持附件下载 |
- 实现重定向
1 | response.sendRedirect("/projectName/url"); // 重定向到其他url |
重定向和转发的区别
- 请求转发时,url不会发生变化。(转发在服务器内部完成,不需要加项目名路径,如"/工程名")
- 重定向时,url会发生变化。(需要加项目名路径,如"/projectName/url")
- 请求转发是服务器级别的,可以访问/WEB-INF/下的资源
- 重定向是浏览器级别的,无法访问/WEB-INF/下的资源
- 请求转发会将斜杠"/"发送给服务器解析,得到http://ip:port/工程名
- 重定向会将斜杠"/"发送给浏览器解析,得到http://ip:port/
在前端文件中写跳转链接时,因其不能得知服务器内部的项目结构,因此需要人为指定contextPath(在Servlet程序中不需要再指定当前项目在服务器内的路径)
细节:当用户提交完请求,浏览器会记录下最后一次请求的全部信息。当用户按下功能键F5,就会发起浏览器记录的最后一次请求。在此情况下如果使用请求转发的方式跳转页面,用户按下F5后会再次发起请求,因此这种情况应该使用重定向。
HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器,HTTP协议中的所有消息信息会被封装到HttpServletRequest,通过该类的方法可以获得客户端传来的请求信息。
- 获取传递的参数
1 | String username = request.getParameter("username"); |
- 请求转发
1 | request.getRequestDispatcher("/success.jsp").forward(requset, response); |
- 获取请求头中Referer信息(浏览器发起请求时的url),可用于重定向回原地址
1 | String url = req.getHeader("Referer"); |
Web中 / 斜杠的不同意义
- 浏览器内代表所有资源:
/**
- 服务器内代表所有资源:
/
在Web中,/ 是一种绝对路径:
- / 如果被浏览器解析,得到的地址是:
http://ip:port/
(指写在静态html代码中,无法被服务器解析,只能被浏览器解析)
1 | <a href="/">斜杠</a> |
- / 如果被服务器解析,得到的地址是:
http://ip:port/工程路径/
1 | // 映射 |
- 特殊情况:
response.sendRedirect("/");
会将斜杠发送给浏览器解析,得到http://ip:port/
,因此需要再加上工程名response.sendRedirect("/projectName/xxx");
/WEB-INF/目录下的资源文件,客户端无法直接访问(即不能在浏览器中输入url直接跳转),而只能在servlet程序中跳转
在IDEA中,"/“代表的项目文件路径为”target/项目名-1.0-SNAPSHOT/
"
在Web应用的前端程序(.jsp)中:
- 不以 / 开始的相对路径找资源时以当前资源的路径为基准,容易出现问题(不推荐使用)
- 以 / 开始的相对路径找资源时以
http://ip:port/
为基准,不包含当前项目名称路径,因此需要在资源前加上${pageContext.request.contextPath}/
以使程序能找到"target/项目名-1.0-SNAPSHOT/
"下的资源文件。例如若想在.jsp文件中引入css文件的路径,需要写href="${pageContext.request.contextPath}/css/style.css"
Session 和 Cookie
关于 Session 和 Cookie 的完整介绍见文章【JavaWeb】Session 和 Cookie
- 会话(Session):用户打开一个浏览器,访问了一些web资源,关闭浏览器,这个过程可以称为一个会话。
- 有状态会话:浏览器能够保存客户端信息的会话。
保存会话
- Cookie:客户端技术(请求,响应),服务器给客户端创建Cookie。是服务器通知客户端保存键值对的一种技术,客户端有了Cookie后,每次请求都会发送给服务器,每个Cookie的大小不能超过4kb
- Session:服务器技术,可以保存用户的会话信息。可以把信息和数据放在session中
Cookie
服务器创建Cookie
服务器获取客户端的Cookie
- 从请求中拿到Cookie信息
- 服务器响应给客户端Cookie
1 | Cookie[] cookies = req.getCookies(); // 获得cookies |
删除Cookie的方法:
- 不设置有效期,关闭浏览器(关闭Session),自动失效;
- 设置有效期,时间为0。
Cookie有效路径Path的设置:通过设置path路径可以过滤掉不符合路径的Cookie。
Session
服务器会给每一个用户(浏览器)创建一个Session对象。一个Session独占一个浏览器,只要浏览器没关,这个Session就一直存在。用户登录之后,整个网站都可以访问到用户信息。
Session技术,底层是基于Cookie技术实现的:每次创建出的Session对象都会保存成一个Cookie对象传给浏览器保存(该Cookie对象的生命周期为Session级别,即关闭浏览器后销毁)。
Session和Cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session是把用户的浏览器写到用户独占的Session中,服务器保存(保存重要的信息,减少资源的浪费)
- Session对象由服务器创建
使用场景:
- 保存一个登录用户的信息
- 购物车信息
- 在整个网站中经常用到的数据
1 | // 在session中存入信息 |
Session销毁方法:
- 手动销毁:
1 | getSession().invalidate(); |
- 自动销毁:设置会话自动过期:web.xml配置
1 | <session-config> |
JSP
Java Server Pages:Java 服务器端页面,也和Servlet一样,用于动态web技术。JSP页面中可以嵌入Java代码,为用户提供动态数据。其主要用于代替Servlet程序回传html页面的数据。
JSP 原理
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet。在Tomcat部署网页后,会为每个JSP文件生成对应的Java代码(放在work目录下),即JSP最终会被转换成Java源码,JSP本质上就是一个Servlet。
只有在访问JSP页面时,才会编译出对应的.class
文件。
在JSP页面中,Java代码会原封还不动的输出,html代码会进行转换:
1 | out.write("<html>\r\n"); |
JSP 基础语法
JSP表达式:将结果输出到客户端
1 | <%-- JSP表达式 |
JSP脚本片段:代码片段会被生成到_jspService
方法中作为Java代码的一部分。
1 | <%-- jsp脚本片段 --%> |
JSP声明:会被编译到JSP生成的Java的类中,作为属性或方法声明。
1 | <%! |
JSP 指令
静态包含:<%@ include file="common/header.jsp" %>
特点:静态包含不会翻译被包含的jsp页面,其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出,两个页面的作用域会冲突。
动态包含:< jsp:include page=" " ></jsp:include>
特点:动态包含会被包含的jsp页面翻译成java代码,两个页面的作用域不会冲突。
1 | <%@ page args... %> |
九大内置对象
- PageContext
- Request
- Response
- Session
- Application【ServletContext】
- Config【ServletConfig】
- out
- page
- exception
四个能够保存数据信息的对象:
- PageContext:保存的数据只在一个页面中有效
- Request:保存的数据只在一次请求中有效,请求转发会携带这个数据
- Session:保存的数据只在一次会话中有效,从打开服务器到关闭服务器
- Application【ServletContext】:保存的数据只在服务器中有效,从打开服务器到关闭服务器
1 | <% |
out 和 response.getWriter() 区别
JSP 标签、JSTL 标签、EL 表达式
1 | <dependency> |
EL(Expression Language)表达式:${}
- 获取数据:
${username}
- 执行运算:
${param.username=="zhangsan"}
- 获取web开发的常用对象:
${param.username}
JSP标签
1 | <jsp:forward page="/jsptag2.jsp"> |
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足,它自定义了许多标签,可以供我们使用 ,标签的功能和Java代码一样。
- 核心标签
- 格式化标签
- SQL标签
- XML标签
JSTL标签库使用步骤:
- 引入对应的taglib才能使用JSTL标签
1 | <%@ taglib prefix="c" uri=:http://java.sun.com/jsp/jstl/core" %> |
- 在Tomcat也需要引入JSTL的包,否则无法解析JSTL库
- 使用其中的方法
1 | <c:if test="${param.username == 'admin'}" var="isAdmin" > |
1 | <c:forEach var="people" items="${list}" begin="1" end="3" step="1"> |
JavaBean
JavaBean有特定的写法:
- 必须有一个无参构造
- 属性必须私有化
- 必须有get/set方法
一般用来和数据库的字段做映射。
ORM:对象关系映射:
- 数据库中的表——>Java中的类
- 数据库中的字段——>Java中的类的属性
- 数据库中的行数据——>Java中的类的对象
MVC 三层架构
MVC:Model View Controller
Controller(Servlet):专注于处理请求以及控制视图跳转
- 接受用户的请求
- 响应给客户端内容(交给业务层处理,接受业务层返回的数据)
- 重定向或转发(视图跳转)
View(JSP):专注于显示网页与数据
- 展示网页界面
- 提供用户操作,为Controller提供请求
Model(数据库):
- 存储数据
Model
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
View
- 展示数据
- 提供链接发起Servlet请求(a,form,img…)
Controller
- 接受用户的请求(req:请求参数,Session信息)
- 交给业务层处理对应的代码,接受业务层返回的结果
- 控制视图的跳转
Filter
面试题:Filter 和 Interceptor 几乎拥有相同的功能,二者有何区别?
- Filter 是 Servlet 定义的原生组件,好处是可以脱离 Spring 应用也能使用;其工作时机早于 Interceptor,在请求映射前执行
- Interceptor 是 Spring 定义的接口,被 Spring 容器管理,可以使用 Spring 的自动装配等功能
Filter 在请求到达 Spring MVC 的 DispatcherServlet
前就会进行拦截过滤,只有通过后才会进入到 Spring MVC 里的请求转发,Interceptor 则是在进入到 DispatcherServlet
后才拦截的。
Filter:过滤器,用来对每个请求进行过滤。责任链模式。可用于:
- 处理中文乱码
- 登录验证
Filter的先后执行顺序由Filter类在web.xml中定义的顺序有关
匹配方式:
- 精确匹配:精确到具体的文件名
- 目录匹配:匹配到指定目录下的所有文件:
/admin/*
- 后缀名匹配:匹配到指定后缀名的文件:
*.html
(不能以/开头)
- 实现
Filter
类的功能(处理中文乱码)
1 | package com.zhao.filter; |
- 在web.xml中配置Filter
1 | <!-- 注册Filter --> |
Filter的使用场景之一(事务):在Filter中捕获Service层的异常
Listener
Listener:监听器
- 实现监听器的接口
1 | package com.zhao.listener; |
- 在web.xml中配置Listener
1 | <listener> |