JavaWeb
Web程序是什么
- 可以提供浏览器访问的网页
- 程序 = 数据结构+算法
Tomcat
Apache Tomcat 是一个开源的实现了 Java Servlet、JavaServer Pages(JSP)、Java Expression Language(EL)和 Java WebSocket 技术的 web 服务器和 servlet 容器
下载并启动Tomcat
注意tomcat10以上注意版本问题
配置Java环境:在本机上配置一个JAVA_HOME的变量
在bin文件内点startup.bat
访问地址localhost:8080
Tomcat配置文件
修改主机名称
Tomcat只能启动通过localhost去访问? 可以修改在C:\Windows\System32\drivers\etc目录下host文件中有映射主机名称步骤如下
修改改主机名称:在conf\service文件中改成自己想要的域名如
www.xxl.com
还要把自己主机的名称一起改掉在C:\Windows\System32\drivers\etc目录下host文件把本来映射localhost的改成www.xxl.com注意是加映射1 2
<!-- tomcat配置文件 --> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" />
修改端口
Tomcat目录中conf\service.xml文件中
|
|
Tip:
- mysql【默认3306】
- http【默认80】.
- https【默认端口443】
相关面试题
- 请你谈谈网站是如何进行访问的!
输入一个域名:回车
检查本机的C:\Windows\System32\driv ers\etc\hosts配置文件有没有这个域名映射
- 有:直接返回对应的ip地址
- 没有:去dns服务器找,能找到就返回,找不到就返回找不到
发布一个web网站
将自己写的网站放到服务器【tomcat】中指定的web应用的文件夹下【webapps】,就可以访问了网站该有的的结构
|
|
IDEA控制台乱码问题
在IDEA编辑器中help中自定义vm option加上这一句-Dfile.encoding=UTF-8
其余的在tomcat log配置文件改
HTTP
- 超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上
- 文本:html,字符….
- 超文本:图片,音乐,视频,定位,地图…..
两个时代
- HTTP/1.0:客户端与web夫区其连接后,只能获得一个web资源,然后断开连接
- HTTP/1.1:客户端与web夫区其连接后,可以获得多个web资源
Request & Response
Request(请求)
请求用于处理用户的网络动作大概流程:客户端 ➡️ 发请求 ➡️ 服务器
请求头部分参数介绍
|
|
Response(响应)
处理完请求之后就会回应给客户端大概流程为:服务器 ➡️ 客户端
响应体部分参数介绍
|
|
响应状态码
- 200:请求响应成功 200
- 3xx:请求重定向
- 重定向:重新到我给你找的新位置去
- 4xx:找不到资源 404
- 5xx:服务器代码错误 500 :服务器代码错误 502:网关错误
请求方法的区别
主要分为两种get和post,其余的delete/put…都是在get和post基础上扩展,为了满足Restful风格
get
:请求能够携带的参数大小有限制,会在浏览器的url地址栏显示数据内容,不安全。但高效post
:请求能够携带的参数有限制,但是比get请求大,不会在浏览器的url地址栏显示数据内容,安全。但相对不高效
Maven
Apache Maven 是一个软件项目管理和理解工具。基于项目对象模型 (POM) 的概念,Maven 可以通过中央信息来管理项目的构建、报告和文档。
简而言之就是包管理工具/项目架构管理工具
下载安装Maven
安装后解压即可
配置环境变量,如果你的Maven下载在
E:\Program Files (x86)\TomcatAndMaven\apache-maven-3.8.6
目录下- M2_HOME:
E:\Program Files (x86)\TomcatAndMaven\apache-maven-3.8.6-bin\apache-maven-3.8.6\bin
- MAVEN_HOME:
E:\Program Files (x86)\TomcatAndMaven\apache-maven-3.8.6-bin\apache-maven-3.8.6
- 还需要在Path环境变量中增加:
E:\Program Files (x86)\TomcatAndMaven\apache-maven-3.8.6-bin\apache-maven-3.8.6\bin
- M2_HOME:
修改Maven配置文件的镜像
修改conf/setting.xml文件,修改镜像仓库地址为国内镜像仓库地址,目的下载jar包速度快
|
|
配置本地仓库
修改conf/setting.xml文件,默认项目依赖都会下载在C:\Users\用户\.m2
中
|
|
IDEA配置Maven
修改在IDEA的maven为我们自己的下载
在设置中设置自动下载源代码
Tip: 以上配置如不想要每个项目都配置一次,则在在IDEA默认全局配置设置
IDEA配置Tomcat
点击当前文件进行配置
配置上下文路径映射,也就是url地址会显示
启动Tomcat,默认首页是index.jsp
项目的结构
POM文件
pom.xml是maven核心配置文件
|
|
出现配置无法生效、导出xml文件问题,解决方案在build中添加resource
|
|
IDEA默认的web.xml版本太低问题:把Tomcat的web.xml文件版本复制过去
|
|
最简单的JavaWeb示例
继承HttpServlet,重写doget,doPost()方法
在web.xml文件中配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0" metadata-complete="true"> <!--web.xml中配置我们的web核心应用 --> <!-- 注册Servlet,一个Servlet标签对应一个类--> <servlet> <servlet-name>helloServlet</servlet-name> <!-- 类的路径--> <servlet-class>com.xxl.HelloServlet</servlet-class> </servlet> <!-- 一个Servlet对应一个Mapping:映射--> <servlet-mapping> <!--这个的名字要跟上面的servlet标签名字一致 --> <servlet-name>helloServlet</servlet-name> <!-- 请求路径--> <!--tomcat10必须加斜杠“/”,而且在第一位--> <url-pattern>/helloServlet</url-pattern> </servlet-mapping> </web-app>
为什么要映射:我们通过url地址访问,每一个地址需要相应的Servlet类处理
Servlet-Mapping
匹配URL请求分发到对应的Servlet类处理,如下将介绍匹配规则
1对1
一个Servlet对应一个Mapping
|
|
1对多
一个Servlet对应多个Mapping
|
|
通用路径
一个Servlet可以指定通用路径
|
|
一个Servlet可以自定义后缀Mapping
|
|
优先级
映射优先级:固定匹配规则 > 通用匹配规则
Maven子摸快
|
|
子目录会有父目录的AGV
|
|
父模块可以用来管理依赖,子摸快可以直接使用
Servlet
- Servlet就是sun公司开发动态Web的一门技术
- Sun公司在这些API提供了一个接口就做:Servlet,如果要开发一个Servlet程序,需要两个步骤
- 编写一个类实现Servlet接口
- 把开发好的Java类部署到web服务器中,实现了Servlet接口的程序叫做Servlet
- Servlet是单例模式
Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求之后,会:
简图
ServletContext
Web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,他代表当前的web应用
共享数据
共享数据: 因为一个web应用只有一个上下文,所有的servlet都可以拿到这个上下文对象,所以数据可以共享
设置数据
1 2 3 4 5 6 7 8 9 10
//设置数据 String username = "xxl"; ServletContext servletContext = req.getServletContext(); servletContext.setAttribute("username",username); String text = "<h1>开始设置数据</h1>"; //流不需要设置type和encoding ServletOutputStream outputStream = resp.getOutputStream(); outputStream.write(text.getBytes(),0,text.getBytes().length); outputStream.close();
拿到数据
1 2 3 4 5 6 7 8 9 10
ServletContext servletContext = req.getServletContext(); String username = (String) servletContext.getAttribute("username"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html"); String name = "姓名:"; //字符流需要设置type和encoding,字节流不需要 PrintWriter writer = resp.getWriter(); writer.print(name+username); writer.close();
获取初始化参数
|
|
转发和重定向
转发
转发:当前文件地址,转发带参数
|
|
重定向
重定向:得带上项目地址,相当于之前重新发起请求,不能携带之前的request中参数
|
|
读取资源文件
- 发现问题在java目录下的properties文件识别不了,解决方案:在Maven篇章写了
- 相对路径:target\servlet-02\WEB-INF\classes,俗称classpath
读取配置文件
|
|
路径问题
|
|
HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过http协议访问服务器,http请求中的所有信息都会被封装到HttpServletRequest对象中,通过这个对象的方法可以获得客户端的所有信息
常用方法
|
|
简单示例
简单模拟写一个登录页
后端
|
|
前端
|
|
获取参数 & 请求转发
|
|
|
|
HttpServletResponse
响应,web服务器接收端客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象和一个代表响应的HttpServletResponse的对象。 - HttpServletRequest可以获取请求过来的参数 - HttpServletResponse可以在这个对象加一些响应的信息
常用方法
- 负责向浏览器发送数据的方法
|
|
负责向浏览器发送的响应头的方法
|
|
响应码
|
|
简单示例
下载文件
|
|
验证码
|
|
重定向
|
|
面试题
请你聊聊重定向和转发的区别:
- 相同点
- 页面都会跳转
- 不同点
- 重定向:url地址栏会变化,不会携带原请求的请求参数
- 转发:url地址栏不会发生变化,会携带原请求的请求参数
Cookie
会话
重点:除了服务器创建的cookie,自己增加的cookie只会在你response回去的那个页面(详细信息见下面图解),也就是说转发会携带请求和cookie,而重定向不会
cookie是有作用范围,范围的大小决定请求的时候能带哪些cookie所以有的时候明明设置了cookie却无法生效,看下图
用户打开浏览器,点击了很多链接,访问多个web资源,然后关闭浏览器,这个过程可以称之为会话
一次会话是指: 好比打电话,当A打给B,电话接通了 会话开始,持续到会话结束。 浏览器访问服务器,就如同打电话,浏览器A给服务器发送请求,访问web程序,该次会话就开始,其中不管浏览器发送了多少请求 ,都为一次会话,直到浏览器关闭,本次会话结束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 解决ajax跨域导致session不一致的问题,由于sessionId是存在cookie,而每次获取getSession() // 都会通过cookie中的sessionId来获取session,如果没有就会创建一个新的session,然后把sessionId存在cookie中 // 把cookie中的sessionId给下一个请求,失败因为跨域原因导致cookie崩创建 String sessionId = "JSESSIONID"; Cookie[] cookies = request.getCookies(); if (cookies != null) { log.info("cookie=不为null"); for (Cookie cookie : cookies) { if (cookie.getName().equals(sessionId)) { Cookie cookie1 = new Cookie(sessionId,cookie.getValue()); response.addCookie(cookie1); } } }
有状态会话
- 第一次去某个网站然后登录,之后会给你标记,下次来的时候,网站识别到这个标记,知道你来过,所以就不用重新登录了
保存会话的两种技术
- cookie:客户端技术 ,存的数据比较少
- session:服务器技术,利用这个技术,可以保存用户的会话信息,可以把数据或者信息放在session中
Cookie的使用方法
cookie常用的方法
1 2 3 4 5
Cookie cookie = new Cookie(); cookie.getName(); //得到cookie的键 cookie.setMaxAge(); //设置cookie的存活期 cookie.getValue(); //得到当前cookie的值 cookie.setPath(); //设置作用范围
从请求中拿到cookie,再响应一个cookie给客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
String h1 = "<h1>"; String h1end = "</h1>"; //查看cookie一般从请求中得到 Cookie[] cookies = req.getCookies(); //cookie不止一个 //响应 ServletOutputStream outputStream = resp.getOutputStream(); //判断有没有cookie if (cookies != null) { for (Cookie ck : cookies) { if (ck.getName().equals("lastLoginTime")) { String text = h1+"上次登录时间:"+ck.getValue()+h1end; outputStream.write(text.getBytes(),0,text.getBytes().length); } } }else { String text = h1+"第一次没有cookie"+h1end; outputStream.write(text.getBytes(),0,text.getBytes().length); } resp.setCharacterEncoding("utf-8"); //添加cookie Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-hh:mm:ss"); String format1 = format.format(date); Cookie lastLoginTime = new Cookie("lastLoginTime",format1); //设置这个cookie存活时间,单位是秒 lastLoginTime.setMaxAge(24*60*60); Cookie cookie = new Cookie("info", "随便写的"); resp.addCookie(lastLoginTime); resp.addCookie(cookie); outputStream.close();
一个网站的cookie上限:一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
cookie大小有限制:4kb
300个cookie是一个浏览器的上限
删除cookie
不设置有效期
设置有效期为0
1 2 3 4
Cookie cookie = new Cookie("name", "xxl"); //cookie.setMaxAge(0) //写在这就是这个会话期间就没了,但没什么意义 resp.addCookie(cookie); //cookie.setMaxAge(0); //写在这跟默认是一样的就是浏览器关闭cookie就没
网络编程时刻注意编码问题
1 2
编码:URLEncoder.encode(); 解码: URLDecoder.decode();
Session
每个人获取的session都不同,只要不是在同一个浏览器
session是存在服务器上,cookie是存在浏览器(每次请求会携带当前页的所有cookie),session对象在服务器默认存活时间未30分钟
对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留。
所以浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session 恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为session设置了一个失效时间,一般是30分钟也就是说这个session可以一直存在,只要服务器不刷新,或者设置一个存话时间(这样浏览器关闭也会存在),当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间
服务器刷新,浏览器关闭/刷新,session就没了,不适合存数据
cookie可以存在浏览器,只要还在cookie存活期cookie就一直存在。
session和cookie关系
1 2 3 4 5 6 7
场景:通过session里用户判断是否登录 设置session时间(是这个session对象在服务器的存活时间,一般为30分钟):如果关闭浏览页再打开Session中还是存着用户信息的.关闭浏览器再打开就要重新登录, (注意session是可以跨同个服务器的多个页面这就是保存用户信息的核心(它存在web上下文中),cookie则不可以,只能在某一页,但是cookie 是存在请求中的,也就是每次请求都会携带当前页的cookie) session是是通过cookie中存的sessionId获得的,但保存sessionId的cookie是服务器自己创建的,一旦关闭浏览器 再次打开页面就会重新创建cookie同时session也会变化,(想要完成“记住我”这种功能,需要cookie和session一起合作) 所以需要设置cookie存活期,浏览器默认创建的cookie存活期为一次会话,也就是浏览器不够就心
什么是Session
- 服务器会给,会给每一个用户(浏览器某个app),创建一个Session对象
- 一个web应用只有一个session并且独占一个浏览器(也就是session是唯一的),也就是换了一个浏览器也有session只是不一样,但这个session独占这个浏览器。只要浏览器没有关闭,这个Session就存在。这一点跟cookie一样
Session和Cookie的区别
- cookie:是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- session:把用户的数据写给用户独占的session中,服务端保存,session对象由服务器创建
Session用法
存数据
|
|
servlet与servlet之间的通信用session
|
|
手动注销session以及session的存的数据
|
|
自动注销session在配置文件(web.xml)中设置session存活时间
|
|
使用场景
- 保存一个登录用户的时间
- 购物车信息
多个用户共享数据
使用ServletContext
- session因为每个用户都有自己的一个唯一的sessionId
- cookie因为每个浏览器的cookie不一致
JSP
JSP文件底层实际是一个Java类
什么是JSP
JSP(Java Server Pager):Java服务器端页面,和Servlet一样,用于动态Web技术,最大的特点:写JSP就像写Html,同时JSP中可以嵌入Java代码
JSP原理
JSP怎么执行的:JSP最终也会转变成一个java类
IDEA的Tomcat工作空间
1
C:\Users\xxl\AppData\Local\JetBrains\IntelliJIdea2022.2\tomcat\e15f62a3-55e4-44b3-b0d0-787c68ff1d5e\work\Catalina\localhost\servlet_04\org\apache\jsp
JSP本质是一个Servlet
1 2 3
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase //HttpJspBase继承了HttpServlet。 implements org.apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports{}
JSP的底层方法
1 2 3 4 5 6 7 8
//初始化 public void _jspInit() { } //销毁 public void _jspDestroy() { } //jsp服务 public void _jspService(final jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response){}
工作原理:如果JSP中有Java代码就原封不动写进去(xxx_jsp.java类),有Html代码就写成字符串,让浏览器去识别
JSP内置对象
|
|
在JSP中写Java代码
|
|
请求一个JSP页面的流程图
JSP基础语法和指令
JSP指令
第一种:<%=java%>这是一个输出的语句,里面的内容直接输出,注意不要写分号。所有地方的变量都可以引用
第二种:<%java%>在这里面我们就可以写一些java代码,for循环之类的。
第三种:<!%java%>写java代码和方法,不同之处在于这个直接在类中
第四种:<%@ %><%@ include file%>将引入的文件和原来的文件合二为一,就是不能有一样的变量….,jsp:includ/则相反
<%@ page … %> | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
---|---|
<%@ include … %> | 包含其他文件 |
<%@ taglib … %> | 引入标签库的定义 |
第五种:<jsp: args />可以在这里写一些配置代码
Java代码中嵌入Html代码
java代码中不能嵌入html代码,可以伪嵌入
1 2 3 4 5 6 7
<% for (int i = 0; i < 5; i++) { %> <h1>hello,world</h1> //实际是把java代码拆分了,中间写上html代码 <% } %>
Html嵌入java代码
1
<h2>姓名:<%=name%></h2>
JSP输出的区别
<%%>这个里面的表达式和代码都是在_jspService()方法中
<!%%>这个里面的表达式和代码都是在xxx_jsp.java类中,这叫jsp声明
注释的区别
|
|
定制错误页面
jsp文件
|
|
web.xml文件
|
|
JSP9大内置对象
- PageContext
- response
- request
- session
- Application【ServletContext】
- Config【ServletConfig】
- out
- page
- exception
示例:
|
|
转发
|
|
四大对象的有效域
PageContext < Request < Session < Application
Jsp标签以及表达式
EL表达式
作用域:${} 小于 <%=%>
作用
- 获取数据
- 执行运算(加减乘除,判断)
- 获取Web常用开发对象
其中之一用法:${arg}等价于<%= arg%>,区别在于:如果 arg不存在,<%= %>会返回null,而${}不会返回东西,还有就是获取变量时变量如果是在Html中就用
param.参数名
,如果是java定义,需要先存起来【session,pageContext,application(ServletContext),request】然后就直接引用存起来的名字。所用的依赖
1 2 3 4 5 6 7 8 9 10 11 12
<!-- jsp表达式依赖 --> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>3.0.1</version> </dependency> <!-- standard标签库的依赖 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
JSP标签
示例
|
|
JSTL表达式
为什么使用:为了弥补Html的不足
核心标签(掌握部分即可,其他类型标签基本不使用)
使用之前先导入
1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
格式化标签
使用之前先导入
1
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
SQL标签
使用之前先导入
1
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
Xml标签
使用之前先导入
1 2
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
简单应用
- 核心库if标签应用
|
|
核心库set、when、choose、otherwise标签应用【注意otherwise,when标签只能在when标签中使用】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
<%-- set标签就是定义变量像javascript var:变量 value:变量值 --%> <c:set var="score" value="drg" ></c:set> <%-- choose相当与ifelse-ifelse --%> <c:choose> <%-- 相当与if,判断会从第一句开始,有一个符合条件就不继续判断了 --%> <%-- 有一个bug如果是随便输入的话它不走else,走的是第一句if ,可能跟他的比较方式有问题 --%> <c:when test="${score >= '90' }"> <h1>优秀</h1> </c:when> <c:when test="${score >= '80' }"> <h1>良好</h1> </c:when> <c:when test="${score <= '60' }"> <h1>不及格</h1> </c:when> <%-- 相当与else --%> <c:otherwise> <c:out value="不优秀"/> </c:otherwise> </c:choose>
核心库的foreach标签的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<% List<String> people = new ArrayList<>(); people.add(0,"xxl0"); people.add(1,"xxl1"); people.add(2,"xxl2"); people.add(3,"xxl3"); people.add(4,"xxl4"); people.add(5,"xxl5"); pageContext.setAttribute("list",people); %> <%-- for (String person : people) {} 这句相当与 <c:forEach items="${people}" var="person"/> for (int i = 0; i < people.size(); i++) {} 这句相当于 <c:forEach items="${people}" var="person" begin="" end=" " step=""/> items:要遍历的对象 var(变量):遍历出的每一个值 begin:从那个开始 默认从0 end:到哪结束 默认到最后 step:步数 默认是1 --%> <h1>第一种用法</h1> <c:forEach items="${list}" var="person"> <h1>${person}</h1> </c:forEach> <h1>第二种用法</h1> <%-- 理想结果:xxl1 xxl3 --%> <c:forEach items="${list}" var="person" begin="1" end="${list.size() - 2}" step="2"> <h1>${person}</h1> </c:forEach>
JavaBean
JavaBean特定的写法
- 必须有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
JavaBean能做什么
一般用于和数据库的数据映射,操作数据做CRUD
ORM(Object Relationship Mapping):对象关系映射
- 表 —> 类
- 列 —-> 属性
- 每行 —-> 对象
Jsp创建一个实体类对象
- jsp、${}、<%=%>的区别
|
|
MVC
MVC(model view controller 模型视图控制器)三层架构,目前Java最流行的开发规范
原理图
MVC三层架构
Model
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(dao)
View
- 展示数据
- 提供链接发起Service请求
- 监听事件
Controller(Servlet)
- 接收用户请求(request,session)
- 交给业务层处理对应的代码
- 控制视图的跳转
Filter(过滤器)
来的请求过滤,回应则不过滤
路径说明:
1 2 3 4 5 6 7
在Spring Boot中,/**和/*是URL模式匹配的表达式,用于配置过滤器的应用范围。 /**:这是一种最广泛的URL模式匹配,表示匹配所有路径,包括多级路径。它会匹配以任意字符开头的路径,直到最后一个路径段,包括子路径和子目录。例如,/user, /user/profile, /user/profile/edit等都会匹配/**。 /*:这是一种比较限定的URL模式匹配,表示匹配单级路径。它只匹配以斜杠(/)开头的路径的第一级路径段,不会匹配子路径和子目录。例如,/user可以匹配/*,但是/user/profile不会匹配/*。 通常情况下,/**用于全局范围的过滤器配置,可以拦截所有的请求。而/*用于特定的路径或模块的过滤器配置,只拦截指定的一级路径。
作用
filter:过滤网站的数据
编写过滤器
第一步:实现过滤器接口,注意如果是write的话需要指定type,outputStream则不需要,还有转型问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
public class FilterDemo01 implements Filter { //初始化:在web服务器启动就初始化 public void init(FilterConfig config) throws ServletException { System.out.println("filter初始化"); } //销毁:在web服务器关闭时被销毁 public void destroy() { System.out.println("filter销毁"); } //主要方法: /* 1:过滤器中代码,在过滤特殊请求的时候都会被执行 2:必须让过滤器继续通行 doFilter(request, response); */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html"); System.out.println("过滤前"); //这句必须要写,不然程序到这里就被拦截停止!,相当于一个链条(chain),继续把这个请求,响应转发下去 chain.doFilter(request, response); System.out.println("过滤后"); } }
第二步:web.xml文件中配置过滤器
1 2 3 4 5 6 7 8 9 10 11
<filter> <filter-name>f1</filter-name> <filter-class>com.xxl.filter.FilterDemo01</filter-class> </filter> <filter-mapping> <filter-name>f1</filter-name> <!-- <url-pattern>/*</url-pattern>表示当前项目路径下的所有servlet都过经过这个过滤器 --> <!-- <url-pattern>/demo01/demo01/*</url-pattern>表示demo01/demo01下的所有请求才会被过滤 --> <!-- 也就是说 url-pattern就是Servlet的url-pattern,就是过滤请求路径 --> <url-pattern>/demo01/demo01</url-pattern> </filter-mapping>
监听器
对某些事件监听,如:session创建、session销毁
编写监听器
实现监听器接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
/** * @author:xxl * @date:2023/1/3 * @ProjectDescription: 监听器例子:统计有多少个用户 */ public class ListenerDemo01 implements HttpSessionListener { //监听session创建的时候 @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("session被创建了"); ServletContext servletContext = se.getSession().getServletContext();; Integer people = (Integer)servletContext.getAttribute("people"); //第一次重启服务器的时候会出现两个session同时存在,这是tomcat的启动、连接的的原因重新部署一下就行了 System.out.println("sessionId:"+se.getSession().getId()); if (people == null) { //第一次创建session servletContext.setAttribute("people",1); }else { people += people; servletContext.setAttribute("people",people); } } //监听session被销毁的时候 @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("session被销毁"); ServletContext servletContext = se.getSession().getServletContext();; Integer people = (Integer)servletContext.getAttribute("people"); if (people != null) { //第一次创建session people -= 1; servletContext.setAttribute("people",people); }else { people = 0; servletContext.setAttribute("people",people); } } }
在web.xml中配置
1 2 3 4 5 6 7 8
<listener> <listener-class>com.xxl.listen.ListenerDemo01</listener-class> </listener> <!-- 自动销毁 --> <session-config> <session-timeout>1</session-timeout> </session-config>
JDBC
JDBC(Java Database Connectivity)是Java语言中的一种API,用于连接和操作关系型数据库。
JDBC为Java程序提供了一种统一的方式来执行SQL语句,从而实现对数据库的访问和操作。它主要包括以下几个部分:
JDBC驱动程序:用于连接到特定类型的数据库。每种数据库(如MySQL、PostgreSQL、Oracle等)都有对应的JDBC驱动程序。
Connection:代表与数据库的连接。通过Connection对象,Java应用程序可以与数据库建立连接。
Statement:用于执行SQL语句。Statement接口有多种类型,如Statement、PreparedStatement和CallableStatement,分别用于执行简单SQL语句、预编译的SQL语句和存储过程。
ResultSet:存储查询结果。ResultSet对象包含了从数据库返回的结果数据,并提供了方法来遍历和读取这些数据。
SQLException:处理JDBC操作中的错误和异常。SQLException类捕获并处理数据库操作中可能发生的错误。
需要的Jar包
maven导入
1 2 3 4 5 6 7 8
<!--数据库连接驱动(必须要导)--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <!--8.0.31对应的数据库版本--> <version>8.0.31</version> </dependency> </dependencies>
示例
连接数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
//配置信息 //characterEncoding=utf-8&useUnicode=true解决中文乱码 String str = "jdbc:mysql://localhost:3306/jdbc_demo01?useUnicode=true&characterEncoding=utf-8"; String username = "xxl"; String password = "xxl123456"; //1、加载驱动 Class driver = Class.forName("com.mysql.cj.jdbc.Driver"); //2.连接数据库 connection代表数据库 Connection connection = DriverManager.getConnection(str, username, password); //3、创建statement statement:向数据库发送sql语句(CRUD) prepared(准备)Statement(预编译):向数据库发送sql语句(CRUD) Statement statement = connection.createStatement(); //PreparedStatement preparedStatement = connection.prepareStatement(); //4.编写sql语句 String sql = "SELECT * FROM users;"; //5.执行查询sql,返回一个resultSet(结果集) ResultSet execute = statement.executeQuery(sql); //必须要加上next while (execute.next()) { System.out.println("id:"+execute.getObject("id")); System.out.println("username:"+execute.getObject("username")); System.out.println("pwd:"+execute.getObject("pwd")); System.out.println("email:"+execute.getObject("email")); System.out.println("birthday:"+execute.getObject("birthday")); System.out.println("---------------------"); } //关闭连接,释放资源(一定要做),先开后关 execute.close(); connection.close();
增删查改
1 2 3 4 5 6 7 8 9 10 11
//4.编写sql语句 String sqlCheck = "SELECT * FROM users;"; //查询一张表 查 String sqlDelete = "DELETE FROM users WHERE id = 20;"; //删除表中数据 删 String sqlInsert = "INSERT INTO users(id,username,pwd,email,birthday)\n" + "VALUES(20,'xxl1','xxl123456','3578144921@qq.com','20030711');"; //插入 增 String sqlUpdate = "UPDATE `account` SET `balance` = 2000.0 WHERE `id` = 1; "; //改 //执行sql语句,返回一个受影响的行数(假如没有成功,就0行受影响,插入一条数据,就1行受影响,这点在sqlyog中比较明显) int i = statement.executeUpdate(sqlInsert);//用于增删改 if (i > 0) { System.out.println("删除成功"); }
JDBC固定步骤有两种
第一种
- 加载驱动(不需要了)
- 连接数据库
- 创建向数据库发送sql语句的对象
- 编写sql
- 执行sql
- 关闭连接,先开后关
|
|
第二种
- 加载驱动
- 连接数据库
- 编写sql语句
- 预编译
- 执行sql语句
- 关闭连接
|
|
占位符
|
|
事务
事务流程
- START TRANSACTION 或 BEGIN 开启一个新事务
- COMMIT 提交当前事务,使其永久化。
- ROLLBACK 回滚当前事务,取消其变更
- SET autocommit 为当前会话启用或者禁用默认的自动提交模式
事务:要么都成功,要么都失败。ACID原则保证数据的安全
数据库事务ACID四大特点:
- 原子性(Atomicity): 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚
- 一致性(Consistency): 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态。例如,银行账户A和B分别有存款5000,一共10000,无论A转账给B,还是B转账给A,两个账户的总额总是为10000
- 隔离性(Isolation): 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
- 持久性(Durability): 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
开启事务 & 提交事务 & 回滚事务
- connection.setAutoCommit(false); //开启事务
- connection.commit(); //提交事务
- connection.rollback(); //出现异常通知数据库,回滚事务
|
|
邮件
邮件发送原理
相关的协议
- 发送邮件:SMTP协议
- 接受邮件:POP3协议
- 附件:mime协议
相关的依赖
|
|
简单邮件
不带附件,纯文本
|
|
复杂邮件
带附件,内容中嵌入照片
MimeBodyPart类(组成邮件的某个部分) & MimeMultipart类(相当于整个邮件对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
public void difficultyMail() throws GeneralSecurityException, MessagingException { Properties properties = new Properties(); //固定写法 properties.setProperty("mail.host","smtp.qq.com"); //设置qq邮件服务器 properties.setProperty("mail.transport","smtp"); //邮件发送协议 properties.setProperty("mail.smtp.auth","true");//需要验证用户名密码 //关于qq邮箱还要设置ssl加密,大厂都这样 MailSSLSocketFactory mailSSLSocketFactory= new MailSSLSocketFactory(); mailSSLSocketFactory.setTrustAllHosts(true); properties.put("mail.smtp.ssl.enable", "true"); properties.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory); //1、创建session对象,这个对象是指在发送邮件的整个过程------------------------- //qq才有的 Session session = Session.getDefaultInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { //发件人,授权码(密码) return new PasswordAuthentication("3578144921@qq.com","prkxrgpngrtccgih"); } }); //开启debug模式监听session session.setDebug(true); //2、通过session对象拿到transport对象-------------------------------------- Transport transport = session.getTransport(); //3、连接上邮件服务器------------------------------------------------------ //服务器 用户名 授权码(qq设置中找) transport.connect("smtp.qq.com","3578144921@qq.com","prkxrgpngrtccgih"); //4、创建邮件------------------------------------------------------------- MimeMessage mimeMessage = new MimeMessage(session); //准备图片 MimeBodyPart img = new MimeBodyPart(); String path = "D:\\Program Files (x86)\\idea\\IDEAproject\\javaweb02-maven\\servlet-09\\src\\main\\resources\\img\\avatar.jpg"; DataHandler dataHandler = new DataHandler(new FileDataSource(path)); img.setDataHandler(dataHandler); //在主体中放入图片数据 img.setContentID("girl.jpg"); //邮件的内容 MimeBodyPart textBody = new MimeBodyPart(); String text = "<h2 style=\"color: red\">正在学习邮件。。。</h2><hr/><img src='cid:girl.jpg'/>"; //文件节点的设置一定要是setContent() textBody.setContent(text,"text/html;charset=UTF-8"); //将文本节点和图片节点混合在一起 MimeMultipart mimeMultipart = new MimeMultipart(); mimeMultipart.addBodyPart(img); mimeMultipart.addBodyPart(textBody); mimeMultipart.setSubType("related"); //设置到邮件中保存修改 mimeMessage.setContent(mimeMultipart); mimeMessage.saveChanges(); //设置邮件标题主题 mimeMessage.setSubject("困难邮件学习"); //发件人 mimeMessage.setFrom(new InternetAddress("3578144921@qq.com")); //收件人 mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("1499476208@qq.com")); //5、接收邮件---------------------------------------------------------------- transport.sendMessage(mimeMessage,mimeMessage.getAllRecipients()); transport.close(); }