C /S:客户端/服务器端
需要安装客户端应用
B/S:浏览器/服务器端
不需要安装客户端应用,对于用户来说只需要记住域名访问就可以,高效,客户端零维护
静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析
如: html、css,、JavaScript
动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器,(浏览器内部含有静态资源解析引擎)
如:servlet/jsp、php、asp....
服务器:安装了服务器软件的计算机 ,比如之前电脑安装了mysql软件,那么你的电脑就是一台mysql服务器,
根据ip地址就可以让其它主机访问到你的mysql服务器,并访问到相应的数据。
服务器软件:接收用户的请求,处理请求,做出响应
web服务器软件:接收用户的请求,处理请求,做出响应。
在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目,也称之为web容器
常见的java相关的web服务器软件:
webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
Tomcat:Apache基金组织,中小型JavaEE服务器,仅支持少量的JavaEE规范servlet/jsp。开源,免费。
JavaEE:Java语言在企业级开发中使用的技术规范的总和,一共规定了13项大的规范
安装:解压压缩包即可,注意:安装目录建议不要有中文和空格
启动:运行startup.bat/startup.sh
停止:运行shutdown.bat/shutdown.sh
将Tomcat集成到IDEA中,并且创建JavaEE的项目,部署项目。
server applet ,运行在服务器端的小程序
Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。
将来我们自定义一个类,实现Servlet接口,复写方法。
创建JavaEE项目
导入依赖
?<dependency>
? ? ?<groupId>javax.servlet</groupId>
? ? ?<artifactId>javax.servlet-api</artifactId>
? ? ?<version>4.0.1</version>
? ?</dependency>
定义一个类,实现Servlet接口
public class ServletDemo1 extends HttpServlet
实现抽象类中的抽象方法
public class ServletDemo1 extends HttpServlet {
?
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?System.out.println("前端发送了一个get请求");
? }
? ?
}
在web.xml中配置:
<web-app>
? ?<display-name>Archetype Created Web Application</display-name>
? ?<servlet>
? ? ? ?<servlet-name>servlet</servlet-name>
? ? ? ?<servlet-class>com.codingfuture.ServletDemo1</servlet-class>
? ?</servlet>
?
? ?<servlet-mapping>
? ? ? ?<servlet-name>servlet</servlet-name>
? ? ? ?<url-pattern>/</url-pattern>
? ?</servlet-mapping>
?
</web-app>
6.访问方式
http://localhost:8080/Test_war_exploded/ServletDemo1
好处:
支持注解配置。可以不需要配置web.xml了
步骤:
创建JavaEE项目
定义一个类,实现Servlet接口
重写方法
在类上使用@WebServlet注解,进行配置
@WebServlet(urlPatterns = "/demo1")
@WebServlet(value = "/demo2")
@WebServlet(name = "/demo3")
@WebServlet("/demo4")
http://localhost:8080/Http_Demo_war_exploded/servletDemo1
http://localhost:8080
/Http_Demo_war_exploded -- 虚拟路径 ?实际开发中我们会将虚拟路径配置成/
/servletDemo1 -- 资源路径 -- 资源路径是工作类的首字母小写
修改之后的路径是:
http://localhost:8080/servletDemo1
<!DOCTYPE html>
<html lang="en">
<head>
? ?<meta charset="UTF-8">
? ?<title>Title</title>
</head>
<body>
?
<form action="/servletDemo1" method="post">
? ?<p>账户:
? ? ? ?<input name="username" type="text">
? ?</p>
? ?<p>
? ? ? 密码: <input name="password" type="password">
? ?</p>
? ?<input type="submit" value="提交">
</form>
?
</body>
</html>
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
?
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?System.out.println("前端发送了一个get请求");
? }
?
? ?@Override
? ?protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?System.out.println("前端发送了一个post请求");
? }
?
}
urlpartten:Servlet访问路径
一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
路径定义规则:
/xxx:路径匹配
/xxx/xxx:多层路径,目录结构
*.do: 扩展名匹配
@WebServlet({"/d2", "/dd2", "/ddd2"})//都可以访问到
@WebServlet("/demo2/user") //多层路径
@WebServlet("/demo2/*") //通配符, *任意字符
@WebServlet("*.do") // 任意字符.do 访问
网络分层模型
IP IPv4 与IPv6
TCP (基于连接) 打电话 电话接通 互相通话 结束挂断
如何实现连接: 三次握手 传输确认 四次挥手
优点:传输稳定性强,适用于对网络通讯要求较高的场景 比如传输文件,发送邮件,浏览网页等等
UDP (基于非连接) 写信 对方是否收到,内容是否完整,顺序是否正确
优点: 速度快,但是可能产生丢包,适用于对实时性要求比较高,对少量丢包没有太大要求,如语音通话,视频直播等
无状态
会话技术
Cookie
Session
Hyper Text Transfer Protocol (http)超文本传输协议 ,定义了,客户端和服务器端通信时,发送数据的格式
基于TCP/IP的高级协议,安全
默认端口号:80
基于请求/响应模型的:一次请求对应一次响应
无状态的:每次请求之间相互独立,不能交互数据
HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了 SSL/TLS 非对称加密协议进行了加密处理。
HTTP和HTTPS使用连接方式不同,默认端口也不一样,HTTP是80,HTTPS是443。
对称加密与非对称加密(CA)
请求方式 请求url 请求协议/版本 GET /login.html HTTP/1.1
请求方式:
HTTP协议有多种请求方式,常用的有2种
GET:
请求参数在请求行中,在url后。
请求的url长度有限制的
不太安全
POST:
请求参数在请求体中
请求的url长度没有限制的
相对安全
请求头:客户端浏览器告诉服务器一些信息 请求头名称: 请求头值 一种键值对形式
常见的请求头:
User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
可以在服务器端获取该头的信息,解决浏览器的兼容性问题
Referer:http://localhost/login.html
告诉服务器,我(当前请求)从哪里来
演示
? ?@Override
? ? ?protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ? ?System.out.println("前端发送了一个post请求");
? ? ? ? ?String header = req.getHeader("User-Agent");
? ? ? ? ?if (header.contains("Chrome")) {
? ? ? ? ? ? ?System.out.println("用户当前使用的是谷歌浏览器");
? ? ? ? }
? ? }
空行,就是用于分割POST请求的请求头,和请求体的。
封装POST请求消息的请求参数的
username: zs
password: 123
注意:username=123 请求体 ,只有post请求才可以查看到,get请求是没有的,get请求参数是在url中。
字符串格式:
POST /login.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests:1
?
username: zs
password: 123
request对象继承体系结构:
ServletRequest -- 父接口
??
HttpServletRequest -- 子接口
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(): ? ? ? ?/day02/demo1
* StringBuffer getRequestURL() :http://localhost/day02/demo1
* URI:统一资源标识符 : demo01/loginServlet ? ?范围大 ? ? ? ?共和国
* URL: ?统一资源定位符 : http://localhost/demo01/loginServlet ? 中华人民共和国
6.获取协议及版本:HTTP/1.1
* String getProtocol()
System.out.println(req.getMethod());//1.获取请求方式 :GET/POST
System.out.println(req.getContextPath());//2.获取虚拟目录:
System.out.println(req.getServletPath());//3.获取Servlet资源路径: /demo3
System.out.println(req.getQueryString());//4.获取get方式请求参数:username=zs
System.out.println(req.getRequestURI());//5.URI:统一资源标识符 :/虚拟目录/demo3
System.out.println(req.getRequestURL());//6.URL:统一资源定位符http://localhost:8080/demo3
System.out.println(req.getProtocol());//7.获取协议及版本:HTTP/1.1HTTP/1.1
方法:
String getHeader(String name):通过请求头的名称获取请求头的值
Enumeration< String > getHeaderNames():获取所有的请求头名称
?//1.获取所有请求头的值
?Enumeration<String> headernames = request.getHeaderNames();
?//2.遍历
?while (headernames.hasMoreElements()) {
?String name = headernames.nextElement();
?//3.根据名称获取头的值
?String value = request.getHeader(name);
?System.out.println(name + "-----" + value);
}
getHeader 介绍,判断客户端是哪个浏览器
//获取请求头数据 user - agent
String agent = req.getHeader("user-agent");//不区分大小写
//判断浏览器版本
if (agent.contains("Chrome")) {
? ? ?//处理兼容性问题
? ?System.out.println("谷歌浏览器");
} else if (agent.contains("Firefox")) {
? ?System.out.println("火狐浏览器");
}
演示:
<!DOCTYPE html>
<html lang="en">
<head>
? ?<meta charset="UTF-8">
? ?<title>Title</title>
</head>
<body>
?
<form action="/servletDemo2" method="post">
? ?<p>账户:
? ? ? ?<input name="username" type="text">
? ?</p>
? ?<p>
? ? ? 密码: <input name="password" type="password">
? ?</p>
? ?<p>
? ? ? ?<input type="checkbox" name="hobby" value="coding"> coding
? ? ? ?<input type="checkbox" name="hobby" value="football"> football
? ? ? ?<input type="checkbox" name="hobby" value="basketball"> basketball
? ?</p>
? ?<input type="submit" value="注册">
</form>
?
</body>
</html>
获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=study&hobby=game
中文乱码问题:
get方式:tomcat8 已经将get方式乱码问题解决了
post方式:会乱码
解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");?
/**
* 获取请求参数通用方式
*/
?
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
?
? ?@Override
? ?protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? //解决post乱码问题 get请求中英文都可以
? ? ? ?//req.setCharacterEncoding("utf-8");
? ? ?
? ? ? ?System.out.println("前端发送了一个post请求");
? ? ? ?//1.根据参数名称获取参数值
? ? ? ?String username = req.getParameter("username");
? ? ? ?String password = req.getParameter("password");
? ? ? ?System.out.println(username);
? ? ? ?System.out.println(password);
? ? ? //2.根据参数名称获取参数值的数组 //String[] getParameterValues(String name)
? ? ? ?String[] hobbys = req.getParameterValues("hobby");
? ? ? ?for (String hobby : hobbys) {
? ? ? ? ? ?System.out.println(hobby);
? ? ? }
? }
}
请求转发:一种在服务器内部的资源跳转方式
步骤:
通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String path)
使用RequestDispatcher对象来进行转发:
forward(ServletRequest request, ServletResponse response)
特点:
浏览器地址栏路径不发生变化
只能转发到当前服务器内部资源中。
转发是一次请求
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
void setAttribute(String name,Object obj):存储数据
Object getAttitude(String name):通过键获取值
void removeAttribute(String name):通过键移除键值对
/**
* 请求转发:一种在服务器内部的资源跳转方式
* 服务器内部资源跳转
* 从一个Servlet跳转到另一个Servlet中
* 这里是servletDemo1 跳转到servletDemo2中
*/
?
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?String usernameValue = req.getParameter("username");
? ? ? ?// request 域
? ? ? ?req.setAttribute("username", usernameValue);
? ? ? ?// 请求转发
? ? ? ?RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servletDemo2");
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("/http://www.baidu.com");
? ? ? ?requestDispatcher.forward(req, resp);
? } ? ?
}
?
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?Object usernameValue = req.getAttribute("username");
? ? ? ?System.out.println(usernameValue);
?
? }
}
session域(多次请求,会话期间)
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?String usernameValue = req.getParameter("username");
? ? ? ?// session 域
? ? ? ?HttpSession session = req.getSession();
? ? ? ?session.setAttribute("username", usernameValue);
? ? ?
? ? ? try {
? ? ? ? ? ?Thread.sleep(5000);
? ? ? ? ? ?// 除此此外,浏览器主动关闭,session域中的数据也会销毁
? ? ? ? ? ?session.removeAttribute("username");
? ? ? } catch (InterruptedException e) {
? ? ? ? ? ?e.printStackTrace();
? ? ? }
? }
}
?
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?HttpSession session = req.getSession();
? ? ? ?Object username = session.getAttribute("username");
? ? ? ?System.out.println(username);
?
? }
}
获取ServletContext(Application域)
Servlet三大域对象: request、session、ServletContext。
ServletContext就是三大域对象之一。
ServletContext是一个全局的储存信息的空间,在服务器启动时创建,在服务器关闭时销毁,
一个JavaWeb应用只创建一个ServletContext对象,
作用范围:所有的用户都可以取得此信息,此信息在整个服务器上被保留。
属性范围值:只要设置一次,则所有的网页窗口都可以取得数据。
方法:
ServletContext servletContext = req.getServletContext();
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("username","zhangsan");
request,一个用户可有多个。
reques:表示一个请求,只要发出一个请求就会创建一个request,它的作用域:仅在当前请求中有效。
用处:常用于服务器间同一请求不同页面之间的参数传递
方法:request.setAttribute();
session,一个用户一个。
会话:用户打开浏览器会话开始,直到关闭浏览器会话才会结束。一次会话期间只会创建一个session对象。
用处:常用于web开发中的登陆验证界面(当用户登录成功后浏览器分配其一个session键值对)。
方法:session.setAttribute();
三大域对象在使用上一样,只是三者作用域范围大小不一样。从小到到范围依次是:request < session < ServletContext
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
?
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?String usernameValue = req.getParameter("username");
? ? ? ?//ServletContext
? ? ? ?ServletContext servletContext = req.getServletContext();
? ? ? ?servletContext.setAttribute("username", usernameValue);
? }
}
?
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?ServletContext servletContext = this.getServletContext();
? ? ? ?Object username = servletContext.getAttribute("username");
? ? ? ?System.out.println(username);
? }
}
响应消息
请求消息:客户端发送给服务器端的数据
数据格式:
请求行
请求头
请求空行
请求体
响应消息:服务器端发送给客户端的数据
数据格式:
响应行
响应头
响应空行
响应体
响应行
组成:协议/版本 响应状态码 状态码描述
HTTP/1.1 200 OK
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
状态码都是3位数字
分类:
1xx:试探性请求,服务器接收客户端消息,没接受完成,等待一段时间后,发送1xx状态码
100: 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分
2xx:成功。代表:200 服务器已经成功处理了请求
3xx:重定向。代表:302(重定向),304(访问缓存)
4xx:客户端错误。
代表:
404(请求路径没有对应的资源)
405:比如请求方式 没有对应的doXxx方法
5xx:服务器端错误。代表:500(服务器内部出现异常) ,比如运算错误
响应头:
格式:
头名称 : 值
常见的响应头:
/* 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
@WebServlet("/servletDemo3")
public class ServletDemo3 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?try {
? ? ? ? ? ?// resp.setCharacterEncoding("utf-8");
? ? ? ? ? ?// Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
? ? ? ? ? ?// text/html;charset=utf-8
? ? ? ? ? ?resp.setContentType("text/html;charset=utf-8");
? ? ? ? ? ?int i = 5 / 0;
? ? ? } catch (ArithmeticException e) {
? ? ? ? ? ?System.out.println(e.getMessage());
? ? ? ? ? ?resp.getWriter().println("<h1>服务器正在维护。。。see you later</h1>");
? ? ? }
? }
}
重定向:资源跳转的方式
代码实现:
设置状态码为302
response.setStatus(302);
设置响应头location
response.setHeader("location","/responseServlet02");
简单的重定向方法
response.sendRedirect("/responseServlet02");
代码示例:
/**
* @author Petrel
*/
@WebServlet("/responseServlet01")
public class ResponseServlet01 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?System.out.println("访问了responseServlet01");
? ? ? ?// 访问 /responseServlet01 会跳转到 /responseServlet02资源
? ? ? ?// 方法一
? ? ? ?// 1.设置状态码为302
? ? ? ?// resp.setStatus(302);
? ? ? ?// 2.置响应头location
? ? ? ?// resp.setHeader("location", "/responseServlet02");
? ? ? ?// 方法二
? ? ? ?// 3.简单的重定向方法
? ? ? ?// resp.sendRedirect("/responseServlet02");
? ? ? ?// resp.sendRedirect("http://www.baidu.com");
? }
}
?
@WebServlet("/responseServlet02")
public class ResponseServlet02 extends HttpServlet {
? ?@Override
? ?protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
? ? ? ?System.out.println("访问了responseServlet02");
? }
}
重定向的特点:redirect
地址栏发生变化
重定向可以访问其它站点(服务器)的资源
重定向是两次请求。不能使用request对象来共享数据
转发的特点:forward
转发地址栏路径不变
转发只能访问当前服务器下的资源
转发是一次请求,可以使用request对象来共享数据
注意:
不能使用重定向来访问request域中的数据