# JavaWeb
***
## 1、基本概念
***
### 1.1、前言
web开发:
* web,网页的意思,www.baidu.com
* 静态web
* html,css
* 提供给所有人看的数据始终不会发生变化!
* 动态web
* 淘宝,几乎是所有的网站;
* 提供给所有人看的数据始终会发生变化!
* 技术栈:Servlet/JSP,ASP,PHP
在Java中,动态web资源开发的技术统称为JavaWeb
### 1.2、web应用程序
web应用程序:可以提供浏览器访问的程序
* a.html,b.html.........多个web资源,可以被外界访问,对外界提供服务;
* 资源存在物理机上面
* URL
* 统一的web资源会被放在同一个文件夹下,web应用程序
* 一个web应用由多部分组成
* html,css,js
* jsp,servlet
* java程序
* jar包
* 配置文件(properties)
web应用程序编写完毕后,若想提供给外部访问;需要一个服务器来统一管理;
### 1.3、静态web
* *.htm,*.html,这些都是网页的后端,如果服务器上一直存在这些东西,我们就可以直接进行读取
![image-20211112143650663](assets/image-20211112143650663.png)
* 静态web存在的缺点
* 微博页面无法动态更新,所有用户看到都是同一个页面
* 轮播图,点击特效:为动态
* javascript
* 无法与数据库交互
### 1.4、动态web
页面会动态展示:“展示效果因人而异”
![image-20211112145114932](assets/image-20211112145114932.png)
缺点
* 如果服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;
* 停机维护
优点
* web页面可以动态更新
* 可以与数据库交互
## 2、web服务器
***
### 2.1、技术讲解
ASP
* 微软
* 在HTML中嵌入了VB脚本
PHP
* 开发速度很快,功能强大,跨平台,代码简单
* 无法承载大访问量的情况
JSP/Servlet:
* sun公司主推的B/S架构
* 基于Jva语言
* 可以承载三高问题带来的影响
### 2.2、web服务器
服务器是一种被动操作,用来处理用户的一些请求和用户一些相应信息;
IIS
**Tomcat**
## 3、Tomcat
***
1. JAVA环境必须有
2. 乱码:修改命令行编码为UTF-8
xml文件可以配置
* 端口号
* 主机名称
* 应用的存放位置
访问网站:
1. 输入域名
2. 检查本机hosts
3. 访问DNS服务器
## 4、Servlet
***
### 4.1、Servlet简介
* Servlet就是sun公司开发动态web的一门技术
* sun在这些API中提供了一个接口叫做:Servlet
* 编写一个类实现这个接口
* 开发好的类部署到web服务器中
### 4.2、HelloServlet
1. 构建一个主工程
2. 关于maven父子工程的理解:
父项目中会有一个
```xml
servlet01
```
子项目中会有一个
```xml
```
父项目中的java子项目可以直接引用
3. 编写一个servlet类,继承HttpServlet接口
```java
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 响应流
PrintWriter writer = resp.getWriter();
writer.print("Hello,Servlet");
}
}
```
4. 为什么编写Servlet的映射
我们写的是JAVA程序,但是需要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的servlet,还需给他一个浏览器能够访问的路径
```xml
Hello
com.servlet.HelloServlet
Hello
/hello
```
5. 配置Tomcat
![image-20211112211142264](assets/image-20211112211142264.png)
### 4.3、Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求之后,会:
![image-20211113134002803](assets/image-20211113134002803.png)
### 4.4、Mapping问题
1. 一个Servlet可以指定一个映射路径
```xml
Hello
/hello
```
2. 一个Servlet可以指定多个映射路径
```xml
Hello
/hello1
Hello
/hello2
```
3. 一个Servlet可以指定通用映射路径------servlet优先级较高,会覆盖默认请求
```xml
Hello
/hello/*
```
4. 指定一些后缀或者前缀
```xml
Hello
*.do
```
5. 默认请求路径------少用
```xml
Hello
/*
```
6. 优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求。
### 4.5、ServletContext
web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用;
#### 4.5.1、共享数据
servlet中保存的数据,在另外的servlet可以拿到。
```java
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("userName", userName);
String userName = (String) servletContext.getAttribute("userName");
```
#### 4.5.2、获取初始化参数
```java
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
```
#### 4.5.3、请求转发
```java
// 该转发会带上d
this.getServletContext().getRequestDispatcher("/gp").forward(req,resp);
```
![image-20211113145845150](assets/image-20211113145845150.png)
通过这张图你就可以看到,转发是在服务器之间进行的,它的意思虽然我没有你想要的资源但是我可以帮你找到,
重定向是告诉你,我Servlet1没有这个资源,但是我告诉你那里有,你自己通过浏览器去找,
#### 4.5.4、读取资源文件
maven由于他的约定大于配置,我们写的配置文件,可能无法被导出或者生效,解决方法
```xml
src/main/resources
**/*.properties
**/*.xml
false
src/main/java
**/*.properties
**/*.xml
false
```
Properties
发现都被打包到了同一个路径下:classes,我们俗称为classpath
通过文件流读取。
### 4.6、HttpServletResponse
webn服务器接收到客户端的http请求,针对请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse
* 如果要获取客户端请求过来的参数:HttpServletRequest
* 如果要找客户端响应的一些信息:HttpServletResponse
#### 4.6.1、常用应用
1. 输出信息
2. 下载文件
1. 获取下载文件的路径
2. 下载的文件名
3. 设置让浏览器能够支持我们需要的东西
4. 获取下载文件的输入流
5. 创建缓冲区
6. 获取OutputStream对象
7. 将OutputStream写入缓冲区
8. 将缓冲区写入磁盘
3. 验证码功能
验证怎么来的?
* 前端实现
* 后端实现,需要用到java的图片类,产生一个图片
4. 重定向
![image-20211113164517356](assets/image-20211113164517356.png)
常见场景:
* 用户登录
```java
// 需要设置改项目的路径
resp.setHeader("Location", "/r/image");
resp.setStatus(HttpServletResponse.SC_FOUND);
resp.sendRedirect("/r/image");
```
重定向和转发区别?
相同点:
* 界面都会实现改变
不同点:
* 一个是web服务器
* 一个是浏览器
* 转发会加上项目路径,而重定向不会
* 重定向:302
* 转发:307
### 4.7、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过http服务请求都被封装到Request下面。
1. 获取前端请求的参数
2. 转发请求
```java
req.getRequestDispatcher("/image").forward(req,resp);
```
## 5、Cookie、Session
***
### 5.1、会话
会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程称之为会话。
有状态会话:保存上次会话的状态
怎么证明自己是西电学生?
1. 发票
2. 登记
一个网站,怎么证明你来过?
客户端 服务端
1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了:cookie
2. 服务器登记你来过了,下次你来的时候我来匹配你:session
### 5.2、保存会话的两种技术
cookie
* 客户端技术(响应,请求)
session
* 服务器技术,利用这个技术,可以保存用户的会话信息!我们可以把信息或者数据放入session
常见场景:网站登录之后,下次不需要登录
### 5.3、cookie
1. 从请求中拿到cookie信息
2. 服务器响应给客户端cookie
```java
Cookie[] cookies = req.getCookies();
```
3. 一般会保存在本地目录下
一个网站cookie是否存在上限
* 一个cookie只能保存一个信息
* 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
* 300个浏览器上限
* cookie大小有限制4kb
删除cookie;
* 不设置有效期,关闭浏览器,自动失效;
* 有效期设置为0,自动消失
### 5.4、Session(重点)
什么是session:
* 服务器会给每一个用户(浏览器创建一个)session对象
* 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在
* 用户登录之后,整个网站都可以访问!保存用户的信息;保存购物车的信息
session和cookie的区别:
* cookie是浏览器保存(可以保存多个)
* session是用户独占,服务器端保存(保存重要信息,减少服务器资源浪费)
* session对象是由服务器创建
session使用场景:
* 保存一个登录用户的信息
* 购物车信息:
* 整个网站中经常会使用的数据
什么时候会被销毁?
话题:当浏览器关闭后,Session就销毁了吗?
答案:存在于浏览器上的唯一标识符JSESSIONID(sessionid)消失了,但是服务器中存放的sessionid并没有立马销毁。
分析:我们知道Session是JSP的九大内置对象(也叫隐含对象)中的一个,它的作用是可以保存当前用户的状态信息,初学它的时候,认为Session的生命周期是从打开一个浏览器窗口发送请求到关闭浏览器窗口,但其实这种说法是不正确的!当一个Session开始时,Servlet容器会创建一个HttpSession对象,那么在HttpSession对象中,可以存放用户状态的信息,Servlet容器为HttpSession对象分配一个唯一标识符即Sessionid,Servlet容器把Sessionid作为一种Cookie保存在客户端的浏览器 中用户每次发出Http请求时,Servlet容器会从HttpServletRequest对象中取出Sessionid,然后根据这个Sessionid找到相应的HttpSession对象,从而获取用户的状态信息。
其实让Session结束生命周期,有以下两种办法:
1. 一个是Session.invalidate()方法,不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;
2. 一个是当前用户和服务器的交互时间超过默认时间后,Session会失效。
## 6、JSP
***
### 6.1、什么是JSP?
java server pages:java服务器端界面,也和servlet一样,用于动态web技术
最大的特点:
* 写JSP就像写HTML
* 区别
* HTML只给用户提供静态数据
* JSP页面中可以嵌入JAVA代码,为用户提供动态数据
### 6.2、JSP原理
* 代码层面没有任何问题
* 服务器内部工作
tomcat中有一个work目录
IDEA中使用tomcat开发会在idea中生成一个work目录
* 浏览器向服务端发送请求,不管访问什么请求,其实都是在访问servlet
* JSP最终会转换为java类
* JSP本质还是一个servlet
1. 判断请求
2. 内置一些对象
```java
final javax.servlet.jsp.PageContext pageContext; // 页面上下文
javax.servlet.http.HttpSession session = null; // session
final javax.servlet.ServletContext application; // applicationcontext
final javax.servlet.ServletConfig config; //配置
javax.servlet.jsp.JspWriter out = null; // out
final java.lang.Object page = this; // page当前页
```
3. 输出页面前增加的代码
```java
response.setContentType("text/html"); // 响应类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
```
4. 以上这些对象我们在JSP页面中直接使用
* 在JSP页面中:
如果是JAVA代码就会被原封不动的输出
如果是HTML代码就会被转换为out.write("
")这样的格式渲染到前端
* 原理图
![image-20211114185115260](assets/image-20211114185115260.png)
### 6.3、JSP基本语法
任何语言都有自己的语法,JPS作为java的一种应用,它拥有自己的扩充语法(了解即可),并且支持所有的java语法
1. JSP表达式
```jsp
<%--JSP表达式
作用:用来将程序的输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
```
2. JSP脚本片段
```jsp
<%
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
out.println("Sum=" + sum + "
");
%>
<%--JSP脚本片段--%>
<%
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
out.println("Sum=" + sum + "
");
%>
<%
for (int i = 0; i < 5; i++) {
%>
Hello,World <%=i%>
<%
}
%>
```
3. jsp声明:会被编译到JSP生产JAVA类中!其他的,就会被生产到_jspservice方法中!
```jsp
<%!
static {
System.out.println("Loading Servlet!");
}
private int g = 0;
public void test() {
System.out.println("in test method");
}
%>
```
4. jsp的注释无法显示在html中
### 6.4、JSP指令
```jsp
<%@page%>
<%--g--%>
<%@include file=""%>
这个与上面的区别:下面的本质还是三个页面而上面是三个部分拼接成一个
jsp:include page="index.jsp"/
```
### 6.5、9大内置对象
* Pagecontext 存东西
* Request 存东西
* Response
* Session 存东西
* Application 存东西
* Config
* out
* page
* Exception
```java
// 保存的数据只在一个页面有效
pageContext.setAttribute("name1", "1");
// 保存的数据只在一次请求中有效,请求转发(重定向无效)会携带这个数据
request.setAttribute("name2", "2");
// 保存的数据只在一次会话有效
session.setAttribute("name3", "3");
// 保存的数据只在服务器中有效,从打开服务器到关闭服务器
application.setAttribute("name4","4");
```
### 6.6、JSP标签、JSTL标签、EL表达式
```jsp
javax.servlet.jsp.jstl
jstl-api
1.2
taglibs
standard
1.1.2
```
EL表达式:${}
* 获取数据
* 执行运算
* 获取web开发的常用对象
JSP标签
```jsp
<%--转发--%>
```
JSTL标签
JSTL标签库的使用就是为了弥补HTML标签的不足;他自定义许多标签,可以供我们使用,标签的功能和java代码一样!
* 核心标签(要求掌握部分)
![image-20211116155018740](assets/image-20211116155018740.png)
* 格式化标签
* SQL 标签
* XML 标签
*
```jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
```
## 7、JavaBean
***
实体类
JavaBean有特点的写法:
* 必须定义无参构造
* 属性必须私有化
* 必须有对应的get/set方法
一般用来和数据库字段做映射ORM;
ORM:对象关系映射
* 表->类
* 字段->属性
* 行记录->对象
People表
| id | name | age | address |
| ---- | ---- | ---- | ------- |
| 1 | tom | 10 | 西安 |
| 2 | lin | 19 | 西安 |
| 3 | pet | 13 | 西安 |
```java
public class People {
private int id;
private String name;
private int age;
private String address;
}
```
```jsp
```
## 8、MVC三次架构
***
什么是MVC:model view controller 模型、 视图、 控制器
### 8.1、早些年
![image-20211116171819380](assets/image-20211116171819380.png)
用户直接访问控制层,控制层直接操作数据库;
```shell
servlet--CRUD--->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
```
### 8.2、MVC三层架构
![image-20211116172558256](assets/image-20211116172558256.png)
Model
* 业务处理:业务逻辑(Service)
* 数据持久层:CRUD(Dao)
View
* 展示数据
* 提供链接发起Servlet请求(a,form, img)
Controller(Servlet)
* 接受用户的请求:req,参数和session信息
* 交给业务层处理响应的代码
* 控制视图的跳转
```
登录----》接受用户的请求---》处理用户的请求(获取参数:username,password)----》交给业务层处理登录业务(判断用户名密码是否正确:事务)-----》Dao层查询用户名和密码是否正确----》数据库
```
## 9、Filter(重点)
***
Filter:过滤器,用来过滤网站的数据;
* 处理中文乱码
* 登录验证
![image-20211116174340271](assets/image-20211116174340271.png)
Filter开发步骤:
1. 导包
![image-20211117161407452](assets/image-20211117161407452.png)
2. 编写过滤器
```java
public class CharacterEncodingFilter implements Filter {
// 初始化:web服务器启动就已经初始化了,随时等待监听
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init CharacterEncodingFilter");
}
// chain:链
/**
* 1.过滤器中的所有代码,在过滤特定请求的时候都会执行
* 2.必须要让过滤器继续通行
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前");
// 让我们的请求继续走,如果不写,程序在这里就被拦截
chain.doFilter(request,response);
System.out.println("CharacterEncodingFilter执行后");
}
// 销毁:web服务器关闭的时候,过滤器会销毁
@Override
public void destroy() {
System.out.println("destroy CharacterEncodingFilter");
}
}
```
3. 在web.xml中配置
```xml
CharacterEncodingFilter
com.filter.CharacterEncodingFilter
CharacterEncodingFilter
/servlet/*
```
## 10、监听器
***
实现一个监听器的接口;(有n种)
1. 重写方法
```java
public class OnlineCountListener implements HttpSessionListener {
// 创建session监听,一旦创建一个session就会触发这个事件
@Override
public void sessionCreated(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = new Integer(1);
} else {
int value = onlineCount.intValue();
onlineCount = new Integer(value + 1);
}
context.setAttribute("OnlineCount", onlineCount);
}
// 销毁session监听,一旦销毁一个session就会触发这个事件
@Override
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = new Integer(0);
} else {
int value = onlineCount.intValue();
onlineCount = new Integer(value - 1);
}
context.setAttribute("OnlineCount", onlineCount);
}
}
```
2. 配置web.xml
```xml
com.listener.OnlineCountListener
```
## 11、过滤器监听器常见应用
***
用户登陆之后才能进入主页!用户注销就不能进入主页!
```java
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 转换过来才能过去session
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if (httpServletRequest.getSession().getAttribute("USER_SESSION") == null) {
httpServletResponse.sendRedirect("/f/error.jsp");
}
chain.doFilter(request,response);
}
```
## 12、JDBC
***
什么是JDBC:Java连接数据库
* 加载驱动
* 连接数据库,代表数据库
* 向数据库发送SQL的对象Statement : CRUD
* 编写SQL (根据业务,不同的SQL)
* 执行SQL
* 关闭连接(先开的后关)
![image-20211117192533110](assets/image-20211117192533110.png)
1. 导入驱动
```xml
mysql
mysql-connector-java
8.0.19
```
2. java语句
```java
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
// 想数据库发送SQL的对象Statement:CRUD
Statement statement = connection.createStatement();
// 编写SQL
String sql = "select * from users";
// 执行SQL,返回结果集
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println("id" + resultSet.getObject("id"));
}
resultSet.close();
connection.close();
statement.close();
```
**事务**
要么都成功,要么都失败!
ACID原则:保证数据的安全
```shell
开启事务
事务提交 commit
事务回滚 rollback
关闭事务
```