简介
web:全球广域网,也称万维网(www),能够通过浏览器访问的网站
JavaWeb:是用Java技术来解决相关web互联网领域的技术栈
JavaWeb技术栈
B/S架构:Browser/Server,浏览器/服务器架构模式,它的特点是,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器,获取Web资源,服务器把Web资源发送给浏览器即可
好处:易于维护升级,服务器端升级后,客户端无需任何部署就可以使用到新的版本
静态资源:HTML、CSS、JavaScript、图片等。负责页面展现
动态资源:Servlet、JSP等。负责逻辑处理
数据库:负责存储数据
HTTP协议:定义通信规则
Web服务器:负责解析HTTP协议,解析请求数据,并发送响应数据
HTTP
概念:HyperText Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则
HTTP协议特点:
1. 基于TCP协议:面向连接,安全
2.基于请求-响应模型的:一次请求对应一次响应
3. HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。
缺点:多次请求间不能共享数据
优点:速度快
请求数据格式
格式
请求数据分为3部分(如下图所示)
1. 请求行:请求数据的第一行。其中GET表示请求方式(请求方式有7种,POST也是其中一种),/表示请求资源路径,HTTP/1.1表示协议版本
2.请求头:第二行开始,格式为key : value形式。
3.请求体:POST请求的最后一 部分,存放请求参数
常见的HTTP请求头
- Host:表示请求的主机名
- User-Agent:浏览器版本,例如Chrome浏览器的标识类似Mozilla/5.0 ..Chrome/79,IE浏览器的标识类似Mozilla/5.0 (Windows NT ... like Gecko
- Accept:表示浏览器能接收的资源类型,如text/*、image/*或者*/*表示所有
- Accept-Language:表示浏览器偏好的语言,服务器可以据此返回不同语言的网页
- Accept-Encoding:表示浏览器可以支持的压缩类型,例如gzip、deflate等
GET请求和POST请求区别
GET请求请求参数在请求行中,没有请求体。POST请求请求参数在请求体中。
GET请求请求参数大小有限制,POST没有
相应数据格式
格式
响应数据分为3部分(如下图所示)
1.响应行:响应数据的第一行。 其中HTTP/1.1表示协议版本,200表示响应状态码,OK表示状态码描述
2.响应头:第二行开始,格式为key : value形式
3.响应体:最后一部分。 存放响应数据
响应状态码
状态码分类 | 说明 |
1xx | 响应中--临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它 |
2xx | 成功--表示请求已经被成功接收, 处理已完成 |
3xx | 重定向一重定向到其它地方:它让客户端再发起一个请求以完成整个处理。 |
4xx | 客户端错误--处理发生错误, 责任在客户端,如:客户端的请求一个不存在的资源, 客户端末被授权,禁止访问等 |
5xx | 服务器端错误--处理发生错误, 责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等 |
状态码大全:https://cloud.tencent.com/developer/chapter/13553
*常见的相应状态码
状态码 | 英文描述 | 解释 |
200 | OK | 客户端请求成功,即处理成功,这是我们最想看到的状态码 |
302 | Found | 指示所请求的资源已移动到由Location响应头给定的URL,浏览器会自动重新访问吧。隐式重定向 |
304 | Not Modified | 告诉客户端,你请求的资源至上次取得后,服务端并未更改,你直接用你本地缓存吧。隐式重定向 |
400 | Bad Request | 客户端请求有语法错误,不能被服务器所理解 |
403 | Forbidden | 服务器收到请求,但是拒绝提供服务,比如:没有权限访问相关资源 |
404 | Not Found | 请求资源不存在,一般是URL输入有误,或者网站资源被删除了 |
428 | Precondition Required | 服务器要求有条件的请求,告诉客户端要想访问该资源,必须携带特定的请求头 |
429 | Too Many Requests | 太多请求,可以限制客户端请求某个资源的数量,配合Retry-After(多长时间后可以请求)响应头一起使用 |
431 | Request Header Fields | 请求头太大,服务器不愿意处理请求,因为它的头部字段太大。请求可以在减少请求头域的大小后重新提交。 |
405 | Method Not Allowed | 请求方式有误,比如应该用GET请求方式的资源,用了POST |
500 | Internal Server Error | 服务器发生不可预期的错误。服务器出异常了,赶紧看日志去吧 |
503 | Service Unavailable | 服务器尚未准备好处理请求,服务器刚刚启动,还未初始化好 |
511 | Network Authentication Required | 客户端需要进行身份验证才能获得网络访问权限 |
常见的HTTP响应头
Content-Type:表示该响应内容的类型,例如text/htmI,image/jpeg
Content-Length:表示该响应内容的长度(字节数)
Content- Encoding:表示该响应压缩算法,例如gzip
Cache-Control:指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒
Tomcat
Web服务器
Web服务器是一个应该程序 (软件) ,对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作,让Web开发更加便捷。主要功能是“提供网上信息浏览服务”
常见服务器软件:Tomcat、jetty、WebLogic、WebSphere
简介
Tomcat是Apache软件基金会一个核心项目, 是一个开源免费的轻量级Web服务器,支持Servlet/JSP少量JavaEE规范。
JavaEE:Java Enterprise Edition, Java企业版。 指Java企业级开发的技术规范总和。包含13项技术规范:JDBC、JNDI、 EJB、 RMI、JSP、 Servlet、 XML、 JMS、 Java IDL、 JTS、JTA、 JavaMail、 JAF
Tomcat也被称为Web容器、Servlet容器。 Servlet 需要依赖于Tomcat才能运行
官网:https://tomcat.apache.org/
基本使用
下载:官网下载
安装:绿色版,直接解压即可
卸载:直接卸载删除目录即可
启动:双击bin\startup.bat
配置:修改启动端口号:conf/server.xml
*HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat时,将不用输入端口号
Tomcat部署项目:将项目放到webapps目录下,即部署完成
*一般JavaWeb项目会被打成war包,然后将war包放到webapps目录下,Tomcat会自动解压缩war文件
IDEA中创建Maven Web项目
Web项目结构
Maven Web项目结构:开发中的项目
部署的JavaWeb项目结构:开发完成,可以部署的项目
编译后的Java字节码文件和resources的资源文件,放到WEB-INF下的classes目录下
pom.xml中依赖坐标对应的jar包,放入WEB-INF下的Iib目录下
创建项目
使用骨架
骨架:项目模板
- 选择web项目骨架,创建项目
- 删除pom.xml中多余的坐标
- 补齐缺失的目录结构
不使用骨架
- 选择web项目骨架,创建项目
- pom.xml中添加打包方式为war
- 补齐缺失的目录结构: webapp
IDEA中使用Tomcat
集成本地Tomcat:将本地Tomcat集成到Idea中,然后进行项目部署即可
IDEA中使用Tomcat-Tomcat Maven插件:pom.xml添加Tomcat插件,使用Maven Helper插件快速启动项目,选中项目,右键--> Run Maven --> tomcat7:run
Servlet
Servlet是Java提供的一门动态web资源开发技术
Servlet是JavaEE规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet
快速入门
1.创建web项目,导入Servlet依赖坐标
<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency>
</dependencies>
2.创建:定义一个类,实现Servlet接口,并重写接口中所有方法,并在service方法中输入一句话
3.配置:在类上使用@WebServlet注解,配置该Servlet的访问路径
@WebServlet("/study")
public class StudyServlet implements Servlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("hello");}@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}
4.访问:启动Tomcat,浏览器输入URL访问该Servlet
Servlet执行流程
Servlet由web服务器创建,Servlet方法由web服务器调用。
Servlet生命周期
对象的生命周期指一个对象从被创建到被销毁的整个过程
Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段
1.加载和实例化:默认情况下,当Servlet第一 次被访问时, 由容器创建Servlet对象 2.初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象, 完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
3. 请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理。
4.服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后, 容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
* 可以通过配置参数设置对象创建的时机
@WebServlet(value = "/study", loadOnStartup = 1)
//负整数:第一次被访问时创建Servlet对象
//0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
*Servlet方法
初始化方法,在Servlet被创建时执行,只执行一次
void init(ServletConfig config)
提供服务方法,每次Servlet被访问, 都会调用该方法
void service(ServletRequest req, ServletResponse res)
销毁方法,当Servlet被销毁时,调用该方法。在内存释放或服务器关闭时销毁Servlet
void destroy()
获取ServletConfig对象
ServletConfig getServletConfig()
获取Servlet信息(比如作者、版本、版权)
String getServletlnfo()
Servlet体系结构
开发B/S架构的web项目,都是针对HTTP协议,所以自定义Servlet会继承HttpServlet。
HttpServlet使用步骤:继承HttpServlet,重写doGet和doPost方法
HttpServlet原理:获取请求方式,并根据不同的请求方式,调用不同的doXxx方法
@WebServlet("/pro")
public class ServletPro extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("get");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("post");}
}
urlPattern配置
Servlet要想被访问,必须配置其访问路径(urlPattern)
一个Servlet,可以配置多个urlPattern
@WebServLet(urlPatterns = {"/demo1", "/demo2"})
urlPattern配置规则:精确匹配、目录匹配、扩展名匹配、任意匹配
精确匹配
配置路径:@WebServle("/user/aaa")
访问路径:localhost:8080/study/user/aaa
目录匹配(当与精确匹配相同时,优先精确匹配)
配置路径:@WebServle("/user/*")
访问路径:localhost:8080/study/user/aaa
localhost:8080/study/user/bbb
扩展名匹配(路径不能以 / 开头)
配置路径:@WebServle("*.txt")
访问路径:localhost:8080/study/user/aaa.txt
localhost:8080/study/user/bbb.txt
任意匹配(/* 优先级高于 /)
配置路径:@WebServle("/")
@WebServle("/*")
访问路径:localhost:8080/study/user/aaa
localhost:8080/study/user/bbb
/ 和 /* 区别:
当我们的项目中的Servlet配置了"/" ,会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet
当我们的项目中配置了 /*,意味着匹配任意访问路径
优先级:精确路径 > 目录路径 > 扩展名路径 > /* > /
XML配置方式
Servlet从3.0版本后开始支持使用注解配置,3.0版本前只支持XML配置文件的配置方式
步骤:1. 编写Servlet类 2.在web.xml中配置该Servlet
<!--配置全类名-->
<servLet><servlet-name>study</servLet-name><servlet-class>com.GLATY.web.servLet.StudyServlet</servLet-class>
</servlet><!--Servlet访问路径-->
<servLet -mapping><servLet-name>study</servLet-name><urL-pattern>/study</url-pattern>
</servLet-mapping>
Request
获取请求数据
继承体系
Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中
使用request对象,查阅JavaEE API文档的HttpServletRequest接口
获取请求数据
请求数据分为3部分:请求行、请求头、请求体
请求行:
GET/request-demg/req1?username=zhangsan HTTP/1.1
方法 | 介绍 |
String getMethod() | 获取请求方式:GET |
String getContextPath() | 获取虚拟目录(项目访问路径):/request-demo |
StringBuffer getRequestURL() | 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1 |
String getRequestURI() | 获取URl(统以资源标识符): /request-demo/req1 |
String getQueryString() | 获取请求参数(GET方式):username= zhangsan&password=123 |
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求行数据System.out.println(req.getMethod());System.out.println(req.getContextPath());System.out.println(req.getRequestURL());System.out.println(req.getRequestURI());System.out.println(req.getQueryString());
}
请求头:
User-Agent: Mozilla/5.0 Chrome/91.0.4472.106
方法 | 介绍 |
String getHeader(String name) | 根据请求头名称,获取值 |
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求头数据;user-agent:浏览器的版本信息System.out.println(req.getHeader("user-agent"));
}
请求体:
username=superbaby&password=123
方法 | 介绍 |
ServletInputStream getInputStream() | 获取字节输入流 |
BufferedReader getReader() | 获取字符输入流 |
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取post请求体//获取流BufferedReader br = req.getReader();//读取数据System.out.println(br.readLine());
}
使用通用方式获取请求参数
方法 | 介绍 |
Map<String, String[ ]> getParameterMap() | 获取所有参数Map集合 |
String[ ] getParameterValues(String niame) | 根据名称获取参数值(数组) |
String getParameter(String name) | 根据名称获取参数值(单个值) |
这样写代码时如果通过get和post要进行的操作一样,可以减少重复的代码(如下)
@WebServlet("/pro3")
public class StudyServlet3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Map<String, String[]> map = req.getParameterMap();for (String temp : map.keySet()) {String[] out = map.get(temp);for (String out0 : out) {System.out.print(out0 + " ");}}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}
}
请求参数中文乱码处理
请求参数如果存在中文数据,则会乱码。原因是因为tomcat进行URL解码时用的是字符集ISO-8859-1
如果是post只需要在获取数据前设置字符输入流的编码为UTF-8即可(字符输入流的编码默认为)。
方法 | 介绍 |
setCharacterEncoding("") ; | 设置字符输入流的编码 |
req.setCharacterEncoding("UTF-8");
如果是get,可以先将数据转换成字节数据,然后再转为字符串即可(该方法也适用于post)
byte[] bys = out0.getBytes(StandardCharsets.ISO_8859_1); //StandardCharsets.ISO_8859_1 也课写为"ISO-8859-1"
String str = new String(bys, StandardCharsets.UTF_8);
Tomcat8.0之后,已经将GET请求乱码问题解决,设置默认的解码方式为UTF-8
请求转发
请求转发(forward):一种在服务器内部的资源跳转方式
实现方式:
req.getRequestDispatcher("资源B路径' ').forward(req, resp);
请求转发资源间共享数据:使用Request对象
方法 | 介绍 |
void setAttribute(String name, Object o) | 存储数据到request域中 |
Object getAttribute(String name) | 根据key,获取值 |
void removeAttribute(String name) | 根据key,删除该键值对 |
请求转发特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器的内部资源
- 一次请求, 可以在转发的资源间使用request共享数据
Response
设置响应数据
设置相应数据功能介绍
响应数据分为3部分:
1.响应行:HTTP/1.1 200 OK
方法 | 介绍 |
void setStatus(int sc) | 设置响应状态码 |
2. 响应头:Content-Type: text/html
方法 | 介绍 |
void setHeader(String name, String value) | 设置响应头键值对 |
3. 响应体:<html><head>head><body></body></html>
方法 | 介绍 |
PrintWriter getWriter() | 获取字符输出流 |
ServletOutputStream getOutputStream() | 获取字节输出流 |
重定向
重定向(Redirect):一种资源跳转方式
实现方式:先设置相应状态码302,然后设置响应头location
resp. setStatus (302);
resp. setHeader( " location",''另一个资源的路径");
resp.setStatus(302);
resp.setHeader("location", "/studyServlet/study");
简化方式:
resp. sendRedirect(''另一个资源的路径");
resp.sendRedirect("/studyServlet/study");
重定向特点:
- 浏览器地址栏路径发生变化
- 可以重定向到任意位置的资源(服务器内部、外部均可)
- 两次请求,不能在多个资源使用request共享数据
路径问题
浏览器使用:需要加虚拟目录(项目访问路径)
服务端使用:不需要加虚拟目录
动态获取虚拟目录:
String context = req.getContextPath();
String context = req.getContextPath();
resp.sendRedirect(context + "/study");
响应字符数据
1.通过Response对象获取字符输出流
PrintWriter writer = resp.getWriter();
2.写数据
writer.write("内容");
resp.setHeader("content-type", "text/html");//告诉浏览器这是HTML文本,默认是纯文本
PrintWriter writer = resp.getWriter();
writer.write("<h1>abc</h1>");
写数据默认用的是ISO-8859-1而不是UTF-8,如果要输入汉语需要更换格式
resp.setContentType("text/html;charset=utf-8");//告诉浏览器这是HTML文本,并设置使用UTF-8字符集写数据
PrintWriter writer = resp.getWriter();
writer.write("<h1>你好</h1>");
响应字节数据
1.通过Response对象获取字符输出流
ServletOutputStream outputStream = resp.getOutputStream();
2.写数据
outputStream.write(字节数据);
IOUtils工具类使用
1.导入坐标
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.9.0</version>
</dependency>
2.使用
IOUtils.copy(输入流, 输出流);
FileInputStream fis = new FileInputStream("src/main/webapp/a.jpg");
ServletOutputStream os = resp.getOutputStream();
IOUtils.copy(fis, os); //导包时要导apache的
JSP
概念:Java Server Pages, Java服务端页面
一种动态的网页技术,其中既可以定义HTML、JS、CSS等静态内容,还可以定义Java代码的动态内容
JSP = HTML+Java
JSP的作用:简化开发,避免了在Servlet中直接输出HTML标签
快速入门
导坐标
<dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope>
</dependency>
建文件
在webapp目录下创建jsp文件
写标签代码
<body><h1>Hello</h1><% System.out.println("^_^");%>
</body>
原理
JSP本质上是一个Servlet4
JSP在被访问时,由JSP容器(Tomcat)将其转换为Java文件(Servlet),在由JSP容器(Tomcat)将其编译,最终对外提供服务的其实就是这个字节码文件
脚本
JSP脚本用于在JSP页面内定义Java代码
JSP脚本分类:
- <%...%>:内容会直接放到_jspService()方法之中
- <%=...%>:内容会放到out.print()中, 作为out.print()的参数
- <%!...%>:内容会放到_jspService(方法之外,被类直接包含
缺点
由于JSP页面内,既可以定义HTML标签,又可以定义Java代码,造成了以下问题:
- 书写麻烦:特别是复杂的页面
- 阅读麻烦
- 复杂度高:运行需要依赖于各种环境, JRE, JSP容器,JavaEE...
- 占内存和磁盘:JSP会自动生成java和.class文件占磁盘,运行的是.class文件占内存
- 调试困难:出错后,需要找到自动生成的.java文件进行调试
- 不利于团队协作:前端人员不会Java,后端人员不精HTML
- ...
EL表达式
Expression Language表达式语言,用于简化JSP页面内的Java代码
主要功能:获取数据
语法: ${expression}
${things}
获取域中存储的key为brands的数据
先写Java代码
@WebServlet("/pro4")
public class StudyServlet4 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//准备数据List<Thing> things = new ArrayList<>();things.add(new Thing("name1", 1));things.add(new Thing("name2", 2));things.add(new Thing("name3", 3));//存储到request域中req.setAttribute("things", things);//转发到jsp文件中req.getRequestDispatcher("study.jsp");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req, resp);}
}
JavaWeb中的四大域对象:
- page:当前页面有效
- request:当前请求有效
- session:当前会话有效
- application:当前应用有效
el表达式获取数据,会依次从这4个域中寻找,直到找到为止
JSTL标签
JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码
快速入门
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%> <%--prefix后的属性可以任意填写,一般写c--%>
<html>
<head><title>Title</title>
</head>
<body>
</body>
</html>
if标签
用来完成逻辑判断,替换Java if else
<c:if test="true"> <%--如果test的值为true则会显示标签内的内容,如果为false则不显示--%><h1>true</h1>
</c:if>
forEach标签
forEach标签
forEach相当于for循环
items:被遍历的容器
var:遍历产生的临时变量
varStatus:遍历状态对象(index从0开始,count从1开始)
begin:开始数
end:结束数
step:步长
<c:forEach items="${things}" var="Thing"><tr align="center"><td>${Thing.id}</td><td>${Thing.name}</td></tr>
</c:forEach><c:forEach begin="0" end="2" step="1" var="i">${i}
</c:forEach>
MVC模式和三层架构
MVC
MVC是一种分层开发的模式, 其中:
M:Model, 业务模型,处理业务
V:View,视图,界面展示
C:Controller,控制器,处理请求,调用模型和视图
MVC好处:
职责单一,互不影响
有利于分工协作
有利于组件重用
三层架构
数据访问层:对数据库的CRUD基本操作
业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能
表现层:接收请求,封装数据,调用业务逻辑层,响应数据