# Javaweb学习
**Repository Path**: hongxiaohan/javaweb_learning
## Basic Information
- **Project Name**: Javaweb学习
- **Description**: Javaweb学习
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2020-08-20
- **Last Updated**: 2024-12-22
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 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资源、这些web资源可以被外界访问。对外界提供服务。
- 能访问到任何一个页面或者资源、都存在世界的任何一个角落的计算机上。
- URL(统一资源定位符)。
- 统一的资源的web资源会被放在一个文件夹。(web应用程序)----->Tomcat(服务器)
- 一个web应用由多部分组成(静态web、动态web)
- html、css、js
- jsp、servlet
- java程序
- jar包
- 配置文件(Properties)
web应用程序编写完后、要被外界访问得部署到服务器上统一管理。
## 1.3、静态web
- *.html、*.css、这些静态资源页面的后缀,如果服务器一直有存在这些东西、我们就可以直接进行读取(网络)

- 静态web存在的缺点
- web页面无法动态更新所有用户看到的都是同一个页面。
- 轮播图、点击特效:伪特效。
- JavaScript(实际开发、拥有最多)。
- 无法和数据库交互(数据无法持久化、用户无法交互)。
## 1.4、动态web
页面动态展示:web页面展示的效果因人而异。

### 缺点:
- 假如服务器的动态web资源出现了错误、我们需要重新编写我们的后台程序、重新发布。
- 停机维护
### 优点:
- Web页面动态更新。所有用户看到的数据不一样
- 它可以和数据库进行交互(数据可以持久化)

# 2、web服务器
## 2.1、技术类型
**ASP**
- 微软(国内最早流行的);
- 在HTML中嵌入VB脚本、ASP + COM;
**PHP**
- PHP开发速度快、功能强大、跨平台、代码容易
- 无法承载大访问量的情况(局限性)
**JSP/Servlet**
B/S:浏览器和服务器
C/s:客户端和服务器
- sun公司主推的B/S架构
- 基于java语言的(所有的大公司、或者一些开源的组件、都是用java写的)
- 可以承载三高问题带来的影响
- 语法像ASP、ASP---->JSP、加强市场的竞争度
## 2.2、web服务器
**Tomcat**

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由[Apache](https://baike.baidu.com/item/Apache/6265)、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用[服务器](https://baike.baidu.com/item/服务器),在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应[HTML](https://baike.baidu.com/item/HTML)([标准通用标记语言](https://baike.baidu.com/item/标准通用标记语言/6805073)下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
Tomcat 实际上运行JSP 页面和Servlet。目前Tomcat最新版本为9.0.37**。**
# 3、HTTP
## 3.1、什么是HTTP
HTTP(超文本协议)是一个简单的请求-响应协议、它通常运行在TCP之上。
- 文本:html、字符串....
- 超文本:图片、音乐、视频、地图.....
- 80端口
HTTPS:安全的
- 443端口
## 4.2、两个时代
- http1.0
- Http/1.0:客户端可以与web服务器连接只能获得一个web资源
- http2.0
- Http/1.1:客户端可以与web服务器连接可以获得多个web资源
## 百度
### 4.1、请求行
- 请求行的请求方式:GET
- 请求方式:GET POST HAED DELETE PUT...
- GET:请求携带的参数比较少、大小有限制, 会在浏览器的URL地址栏上显示内容、不安全、但是高效。
- POST:请求携带的参数没有限制、大小没有限制、不会在浏览器的URL地址栏显示内容、安全、但是不高效
### 4.2、消息头
```java
Accept:告诉浏览器、它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器、它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器、请求完成是断开还是保持连接
Host:主机
```
### 4.3、Http请求Request
- 客户端----发请求(Request)-----服务器
```java
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET 请求方法(GET、POST)
Status Code: 200 OK 状态码:200(正常)
Remote Address: 14.215.177.39:443 远程地址
```
```java
Accept:text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
```
### 4.4、Http响应Response
- 服务器---响应(Response)----客户端
```java
Cache-Control: private 缓存控制
Connection: keep-alive 保持连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型
```
#### 1、响应体
```java
Accept:告诉浏览器、它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器、它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器、请求完成是断开还是保持连接
Host:主机
```
#### 2、响应状态码
200:请求响应成功 200
3xx:请求重定向
- 重定向:重新定位位置
4xx:找不到资源 404
- 资源不存在
5xx: 服务器代码错误 500
# 4、Servlet
## 4.1、什么是Servlet?
Servlet(Server Applet)是[Java](https://baike.baidu.com/item/Java/85979) Servlet的简称,称为小服务程序或服务连接器,用Java编写的[服务器](https://baike.baidu.com/item/服务器/100571)端程序,具有独立于平台和[协议](https://baike.baidu.com/item/协议/13020269)的特性,主要功能在于交互式地浏览和生成数据,生成动态[Web](https://baike.baidu.com/item/Web/150564)内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
最早支持Servlet标准的是JavaSoft的Java [Web Server](https://baike.baidu.com/item/Web Server/9306055),此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。
## 4.2、HelloServlet
**1、定义HelloServlet类**
(继承HttpServlet接口重写 doGet() doPost()方法)
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/19 18:46
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("你好JavaWeb");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
```
**2、配置Servlet**
在web.xml中配置:
```java
helloServlet
cn.hxh.servlet.HelloServlet
helloServlet
/hello
```
**3、配置Tomcat**
注意:配置项目发布的路径
**4、启动测试 OK!**


这里的乱码可以通过setServletContext("text/html;charset=UTF-8")进行配置;
## 4.3、Servlet原理
Servlet是由Web服务器调用、web服务器在收到浏览器请求之后、会如图所示:

## 4.4、ServletContext
Web容器启动后的时候、它会为每个web程序创建一个对应的ServletContext对象。它代表当前的web应用。
### 1、ServletContext对象
* 概念:代表Web应用、可以和程序的容器进行通讯
* 获取方法
* //获取context对象第一种方法 Request
* ServletContext Context1 = req.getServletContext();
* //获取context对象第二种方法 HttpServlet
* ServletContext Context2 = this.getServletContext();
* 功能:
* 获取MIME类型
* MIME类型:互联网通讯过程定义的一种文件类型
* 格式 : 大类型/小类型 text/html image/jpeg
```java
public class ContextDemo01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取context对象第一种方法 Request
ServletContext Context1 = req.getServletContext();
//获取context对象第二种方法 HttpServlet
ServletContext Context2 = this.getServletContext();
/**
* 单例模式
* 两个对象地址一样
*/
}
}
```
### 2、共享数据

**2.1编写ServletContext类**
```java
package cn.hxh.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/19 18:46
*/
public class ServletContext01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = "洪潇涵";
//将数据存在ServletContext(以键值对形式存储)
servletContext.setAttribute("user",name);
System.out.println("user键内容存储成功");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
```
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/19 18:46
*/
public class ServletContext02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
//获取ServletContext01存储的数据
String user = (String) this.getServletContext().getAttribute("user");
writer.print("你好"+user);
System.out.println("获取ServletContext01数据成功");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
```
**2.2将servlet注册到web.xml**
```xml
ServletContext01
cn.hxh.servlet.ServletContext02
ServletContext02
cn.hxh.servlet.ServletContext01
ServletContext01
/a
ServletContext02
/b
```
**2.3运行测试**
如果我们第一个访问的是/b 如图所示:

**原因:**获取不到存储的数据-->null
那是因为我们没有请求/a -->servlet 所以ServletContext并没有存储数据
如果我们第一个先访问的是/a 再访问/b 如图所示:

测试完毕!
### 3、获取初始化参数
```xml
url
jdbc:mysql://localhost:3306/mybatis
```
```java
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//获取初始化参数
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
}
```
### 4、请求转发
```java
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
System.out.println("进入了ServletContext04");
servletContext.getRequestDispatcher("/c").forward(req,resp);
}
```
* 重定向
* 资源的跳转
* resp.sendRedirect("跳转路径");
* 重定向特点
* 1、URL发生变化
* 2、请求2次
* 3、不能资源共享
* 4、可以访问本服务器之外的站点
* 转发特点
* 1、URL不发生变化
* 2、请求一次
* 3、资源共享
* 4、只能访问本服务器的资源
重定向是客户端路径 必须要加虚拟路径
转发是服务器路径不需要加虚拟路径
虚拟目录是可以改变的我们一个不能把一个虚拟路径写死了
而是使用一个变量保留虚拟目录的路径
这样子避免以后改虚拟路径的时候代码要进行改变
客户端路径
重定向、、form标签
### 5、读取资源文件
Properties
- 在java目录下新建properties
- 在resources目录下新建properties
发现:都被打包到同一个路径下:classes、我们俗称为这路径为class path:
思路:需要一个文件流
```properties
username=root
password=333
```
```java
package cn.hxh.servlet;
import javax.servlet.ServletContext;
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.InputStream;
import java.util.Properties;
/**
* @Author: HongXiaoHan
* @Description properties读取配置文件
* @Date: 2020/8/19 20:52
*/
@WebServlet("/e") //基于注解实现不需要注册
public class ServletContext05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
resp.getWriter().print(username+":"+password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
```
访问测试即可。

## 4.5HttpServletResponse
web服务器接收客户端的Http请求、针对请求分别创建一个个
代表请求的HttpServletRequest
代表响应的HttpServletResponse
- 如果要获取客户端请求过来的参数:HttpServletRequest
- 如果给客户端响应信息: HttpServletResponse
### 1、简单分类
**负责向浏览器发送数据的常用方法:**
```java
public ServletOutputStream getOutputStream() throws IOException;
public PrintWriter getWriter() throws IOException;
```
**负责向浏览器发送响应体的常用方法:**
```java
public void setCharacterEncoding(String charset);
public void setContentType(String type);
```
**响应状态码:**
```java
public static final int SC_CONTINUE = 100;
public static final int SC_SWITCHING_PROTOCOLS = 101;
public static final int SC_OK = 200;
public static final int SC_CREATED = 201;
public static final int SC_ACCEPTED = 202;
public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
public static final int SC_NO_CONTENT = 204;
public static final int SC_RESET_CONTENT = 205;
public static final int SC_PARTIAL_CONTENT = 206;
public static final int SC_MULTIPLE_CHOICES = 300;
public static final int SC_MOVED_PERMANENTLY = 301;
public static final int SC_MOVED_TEMPORARILY = 302;
public static final int SC_FOUND = 302;
public static final int SC_SEE_OTHER = 303;
public static final int SC_NOT_MODIFIED = 304;
public static final int SC_USE_PROXY = 305;
public static final int SC_TEMPORARY_REDIRECT = 307;
public static final int SC_BAD_REQUEST = 400;
public static final int SC_UNAUTHORIZED = 401;
public static final int SC_PAYMENT_REQUIRED = 402;
public static final int SC_FORBIDDEN = 403;
public static final int SC_NOT_FOUND = 404;
public static final int SC_METHOD_NOT_ALLOWED = 405;
public static final int SC_NOT_ACCEPTABLE = 406;
public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
public static final int SC_REQUEST_TIMEOUT = 408;
public static final int SC_CONFLICT = 409;
public static final int SC_GONE = 410;
public static final int SC_LENGTH_REQUIRED = 411;
public static final int SC_PRECONDITION_FAILED = 412;
public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;
public static final int SC_REQUEST_URI_TOO_LONG = 414;
public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
public static final int SC_EXPECTATION_FAILED = 417;
public static final int SC_INTERNAL_SERVER_ERROR = 500;
public static final int SC_NOT_IMPLEMENTED = 501;
public static final int SC_BAD_GATEWAY = 502;
public static final int SC_SERVICE_UNAVAILABLE = 503;
public static final int SC_GATEWAY_TIMEOUT = 504;
public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
```
### 2、常见应用
**下载文件**
1. 要下载的文件路径
2. 下载文件名是什么?
3. 设置浏览器支持下载的文件
4. 获取下载文件流
5. 创建缓冲区
6. 获取OutputStream对象
7. 将FileOutputStream流写入buffer缓冲区
8. 使用OutputStream将缓冲区的数据输出到客户端
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/19 21:57
*/
public class FileDowloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取下载的资源路径
FileInputStream in = new FileInputStream("D:\\Documents\\Pictures\\二次元\\8ceaabdd0d174bea1696e940bdde77cc.jpeg");
//设置响应头
resp.setHeader("Content-Disposition","attachment;filename="+URLDecoder.decode("Test.jpeg","UTF-8"));
//获取输出流
ServletOutputStream outputStream = resp.getOutputStream();
//设置缓冲区
int len = 0;
byte[] bytes = new byte[1024];
while ((len = in.read(bytes)) != -1) {
outputStream.write(bytes,0,len);
}
in.close();
outputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
```
### 3、验证码功能
验证码怎么来?
- 前端实现
- 后端实现:用到Java的图片类、生成一个图片、响应到客户端
```java
package cn.hxh.servlet;
import javax.imageio.ImageIO;
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.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/19 22:29
*/
@WebServlet("/images")
public class ImagesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器5秒后刷新
resp.setHeader("refresh","3");
//在内存中生成图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics = (Graphics2D) image.getGraphics();
//设置图片背景颜色
graphics.setColor(Color.black);
graphics.fillRect(0,0,80,20);
//给图片写数据
graphics.setColor(Color.white);
graphics.setFont(new Font(null,Font.BOLD,20));
graphics.drawString(getRandom(),0,20);
resp.setContentType("image/jpeg");
//网站缓存关闭
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
ImageIO.write(image,"jpg",resp.getOutputStream());
}
public static String getRandom(){
Random random = new Random();
String s = random.nextInt(99999)+"";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 7; i++){
buffer.append(s);
}
String str = buffer.toString().substring(0, 4);
return str;
}
}
```
### 4、实现重定向

B一个web资源收到A的请求后、B会去通知A去访问另一个web资源c、这个过程就是重定向。
**常见场景:**
- 用户登录
```java
public void sendRedirect(String location) throws IOException;
```
测试
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/20 10:13
*/
public class SendRedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/images");
}
}
```
面试题:请你聊聊重定向和转发的区别?
相同点:
- 都会实现页面跳转。
不同点:
- 重定向没有数据共享、转发有数据共享。
- 重定向是请求两个URL、转发只请求一次。
- 重定向可以访问的作用域是所有URL、转发只能访问当前的服务器URL。
- 重定向请求的URL会发生变化、转发的请求的URL不会发生变化。
## 4.6HttpServletRequest
### 1、获取前端参数
**常用方法**
```java
public String getParameter(String name);
public String[] getParameterValues(String name);
```
**以下测试:**
**前端:**
```jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/8/19
Time: 22:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Hello World!
点击下载
```
```jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/8/20
Time: 10:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登陆成功
```
**后端:**
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/20 10:26
*/
public class RequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
resp.sendRedirect(this.getServletContext().getContextPath()+"/success.jsp");
}
}
```
运行结果:


### 2、请求转发
**编写后台**
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/20 11:18
*/
public class ForWardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//转发学习 (记住转发的/是在当前服务器的默认路径 没有多级路径的情况下不要加入项目名的路径)
req.getRequestDispatcher("success.jsp").forward(req,resp);
}
}
```
**注册Servlet到xml**
```xml
ForWardServlet
cn.hxh.servlet.ForWardServlet
ForWardServlet
/forward
```
**运行结果**

# 5、会话
**会话:**用户打开浏览器、点击的链接访问的web资源、一直到关闭浏览器。这一个过程就是会话。
**有状态会话:**一个同学来个教室、下次再来教室。我们就会知道这个同学曾经来过、这个过程就是有状态会话。
**如何证明你是一个学校的学生?**
你 学校
1. 学校信息登记表 学校标记你是该学校学生
2. 学生证 学校给你学生证
**一个网站---->如何证明你来过?**
客户端 服务端
1. 服务器给客户端一个信件、客户端下次访问服务器带上信件即可。-----> cookie
2. 服务器标记你来过了、下次你来访问时服务器来匹配你。----->Seesion
## 1、Cookie
1. 从请求拿到数据cookie信息
2. 服务器拿到cookie信息进行操作响应
```java
//常用方法
public Cookie(String name, String value);//构造方法
public void setMaxAge(int expiry);//持久化硬盘最大值时间
public String getName();//获取该cookie名字
public String getValue();//获取该cookie内容
public void setValue(String newValue);//设置该cookie内容
Cookie[] cookies = request.getCookies();//获取所有cookie
```
**案例:记住我上一次访问时间**
**前端:**
```xml
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/8/20
Time: 11:53
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
${pageContext.request.getAttribute("time")}
```
**后端:**
```java
package cn.hxh.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/20 11:44
*/
//保存用户上一次访问的时间
public class CookieServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
String format = s.format(new Date());
//搜索是否存在该cookie
Cookie[] cookies = req.getCookies();
//标志
boolean flag = false;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("time")) {
flag = true;
break;
}
if (!cookie.getName().equals("time")) {
flag = false;
}
}
}
//存在time cookie
if (flag){
for (Cookie cookie : cookies) {
if (cookie.getName().equals("time")) {
//取cookie
String value = cookie.getValue();
//重置cookie
cookie.setValue(format);
//设置一天有效期
cookie.setMaxAge(60 * 60 * 24);
resp.addCookie(cookie);
req.setAttribute("time","你上次的访问时间:"+value);
break;
}
}
}
if (!flag){
//第一次如果没有 就进行cookie存储
Cookie cookie = new Cookie("time", format);
//设置一天有效期
cookie.setMaxAge(60 * 60 * 24);
resp.addCookie(cookie);
req.setAttribute("time", "欢迎您的访问");
}
req.getRequestDispatcher("time.jsp").forward(req, resp);
}
}
```
**注册:**
```xml
CookieServlet01
cn.hxh.servlet.CookieServlet01
CookieServlet01
/cookie
```
**测试结果:**

## 2、Session(重点)

服务端技术、利用Session可以保存用户信息,可以把用户数据保存在Session中、来判断这个用户是否在访问服务端。
什么是session?
- 服务器会给客户端创建一个对象
- 一个session占一个浏览器、只要浏览器没关、这个seesion就存在
- 用户登录后整个网站都可以访问。-->保存用户信息............
```jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/8/20
Time: 13:43
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
```
```java
package cn.hxh.servlet;
import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/20 13:42
*/
@WebServlet("/session")
public class SessionServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String flag = req.getParameter("flag");
HttpSession session = req.getSession();
ServletContext servletContext = req.getServletContext();
if (flag.equals("1")) {
session.setAttribute("user", "小涵");
servletContext.setAttribute("aa","小涵的servletContext");
}
if (flag.equals("2")) {
session.setAttribute("user", "小潇");
servletContext.setAttribute("aa","小潇的servletContext");
}
String user = (String) session.getAttribute("user");
System.out.println(user+"登录了");
System.out.println(servletContext.getAttribute("aa"));
}
}
```
```bash
小潇登录了
小潇的servletContext
小涵登录了
小涵的servletContext
小涵登录了
小涵的servletContext
小潇登录了
小涵的servletContext
```
可见:servletContext的作用域十分大、可以给每一个人进行修改、而session是每一个人独一无二的。并不能进行修改。(如同对象的成员变量和静态变量一样)
# 6、JSP
### 6.1、什么是JSP
Java Server Pages : Java服务端页面、和Servlet一样、应用动态Web技术!
最大特点:
- 写JSP和写HTML一样
- 区别:
- JSP可以嵌入Java代码、为用户提供动态数据
- HTML只能给用户提供静态数据
### 6.2、JSP基础语法
1. 指令
* 作用:用于配置JSP页面,导入资源文件
* 格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
* 分类:
1. page : 配置JSP页面的
* contentType:等同于response.setContentType()
1. 设置响应体的mime类型以及字符集
2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
* import:导包
* errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
* isErrorPage:标识当前也是是否是错误页面。
* true:是,可以使用内置对象exception
* false:否。默认值。不可以使用内置对象exception
2. include : 页面包含的。导入页面的资源文件
* <%@include file="top.jsp"%>
3. taglib : 导入资源
* <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
* prefix:前缀,自定义的
2. 注释:
1. html注释:
:只能注释html代码片段
2. jsp注释:推荐使用
<%-- --%>:可以注释所有
3. 内置对象
* 在jsp页面中不需要创建,直接使用的对象
* 一共有9个:
变量名 真实类型 作用
* pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象
* request HttpServletRequest 一次请求访问的多个资源(转发)
* session HttpSession 一次会话的多个请求间
* application ServletContext 所有用户间共享数据
* response HttpServletResponse 响应对象
* page Object 当前页面(Servlet)的对象 this
* out JspWriter 输出对象,数据输出到页面上
* config ServletConfig Servlet的配置对象
* exception Throwable 异常对象
### 6.3、EL表达式
1. 概念:Expression Language 表达式语言
2. 作用:替换和简化jsp页面中java代码的编写
3. 语法:${表达式}
4. 注意:
* jsp默认支持el表达式的。如果要忽略el表达式
1. 设置jsp中page指令中:isELIgnored="true" 忽略当前jsp页面中所有的el表达式
2. \${表达式} :忽略当前这个el表达式
5. 使用:
1. 运算:
* 运算符:
1. 算数运算符: + - * /(div) %(mod)
2. 比较运算符: > < >= <= == !=
3. 逻辑运算符: &&(and) ||(or) !(not)
4. 空运算符: empty
* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
2. 获取值
1. el表达式只能从域对象中获取值
2. 语法:
1. ${域名称.键名}:从指定域中获取指定键的值
* 域名称:
1. pageScope --> pageContext
2. requestScope --> request
3. sessionScope --> session
4. applicationScope --> application(ServletContext)
* 举例:在request域中存储了name=张三
* 获取:${requestScope.name}
6. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
3. 获取对象、List集合、Map集合的值
1. 对象:${域名称.键名.属性名}
* 本质上会去调用对象的getter方法
2. List集合:${域名称.键名[索引]}
3. Map集合:
* ${域名称.键名.key名称}
* ${域名称.键名["key名称"]}
3. 隐式对象:
* el表达式中有11个隐式对象
* pageContext:
* 获取jsp其他八个内置对象
* ${pageContext.request.contextPath}:动态获取虚拟目录
### 6.4、JSTL
1. 概念:JavaServer Pages Tag Library JSP标准标签库
* 是由Apache组织提供的开源的免费的jsp标签 <标签>
2. 作用:用于简化和替换jsp页面上的java代码
3. 使用步骤:
1. 导入jstl相关jar包
2. 引入标签库:taglib指令: <%@ taglib %>
3. 使用标签
4. 常用的JSTL标签
1. if:相当于java代码的if语句
1. 属性:
* test 必须属性,接受boolean表达式
* 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
* 一般情况下,test属性值会结合el表达式一起使用
2. 注意:
* c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
2. choose:相当于java代码的switch语句
1. 使用choose标签声明 相当于switch声明
3. 使用when标签做判断 相当于case
4. 使用otherwise标签做其他情况的声明 相当于default
5. foreach:相当于java代码的for语句
# 7、JavaBean
实体类 (JavaBean还有一些其他的别名pojo、domain.......)
JavaBean特定写法:
- 必须有一个无参构造
- 属性必须私有化
- 必须有get/set方法
一般用于和数据库一一映射:ORM
ORM:对象关系映射
- 表=====》类
- 字段=====》属性
- 行记录====》对象
**people表**
| id | name | age |
| ---- | ---- | ---- |
| 1 | 小海 | 18 |
| 2 | 小明 | 17 |
| 3 | 小花 | 18 |
```java
class people{
private int id;
private String name;
private int age;
}
```
# 8、MVC:开发模式
### 1.jsp演变历史
1. 早期只有servlet,只能使用response输出标签数据,非常麻烦
2. 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作
3. 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性
### 2.MVC:
1. M:Model,模型。JavaBean
* 完成具体的业务操作,如:查询数据库,封装对象
2. V:View,视图。JSP
* 展示数据
3. C:Controller,控制器。Servlet
* 获取用户的输入
* 调用模型
* 将数据交给视图进行展示
### 3.优缺点:
1. 优点:
1. 耦合性低,方便维护,可以利于分工协作
2. 重用性高
2. 缺点:
1. 使得项目架构变得复杂,对开发人员要求高
# 9、Fileter(重点)
Fileter:过滤器、过滤网站数据。
- 中文乱码
- 登陆验证

## 1.导包

## 2.编写过滤器
实现过滤器接口即可
```java
package cn.hxh.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/21 12:15
*/
public class CharSetFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@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");
chain.doFilter(request,response);
}
}
```
## 3.在web.xml配置filter过滤器
```xml
CharSetFilter
cn.hxh.filter.CharSetFilter
CharSetFilter
/*
```
# 10、Listener
Listener:监听器
实现一个监听器接口
### 1.编写监听器(实现监听器的接口)
```java
package cn.hxh.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @Author: HongXiaoHan
* @Description
* @Date: 2020/8/21 13:06
*/
public class MyListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
System.out.println(se.getSession().getId());
if (onlineCount == null) {
onlineCount = 1;
} else {
onlineCount = onlineCount + 1;
}
servletContext.setAttribute("OnlineCount", onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
onlineCount = onlineCount - 1;
servletContext.setAttribute("OnlineCount", onlineCount);
}
}
```
### 2.在web.xml注册监
```xml
cn.hxh.listener.MyListener
```
**总结:该内容已经很少遇到了。。根据现实情况使用。**