创建 web项目,导入 Servlet依赖坐标
<dependency>
<groupId>javax.servlet</groupId
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
创建:定义一个类,实现 Servlet接口,并重写接口中所有方法,并在 service方法中输入一句话
public class ServletDemo1 implements Servlet {
public void service(){}
}
配置:在类上使用@WebServlet 注解,配置该 Servlet的访问路径
@WebServlet("/demo1") public class ServletDemo1 implements Servlet {
访问:启动 Tomcat,浏览器输入URL 访问该Servlet
http://localhost:8080/web-demo/demo1
举例说明
http://localhost:8080/web-demo/demo1
http://localhost:8080
------对应Tomcat服务器/web-demo
------对应某个项目demo1
------对应Tomcat创建的Servlet@WebServlet(urlPattern = {"/demo1"."/demo2"})
@WebServlet("/user/select")
@WebServlet("/user/*")
@WebServlet("*.do")
@WebServlet("/")或@WebServlet("/*")
Request:获取请求数据
Response:设置相应数据
请求行包含三块内容,分别是请求方式
、请求资源路径
、HTTP协议及版本
获取请求方式: GET
String getMethod()
获取虚拟目录(项目访问路径): /request-demo
String getContextPath()
获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
StringBuffer getRequestURL()
获取URI(统一资源标识符): /request-demo/req1
String getRequestURI()
获取请求参数(GET方式): username=zhangsan&password=123
String getQueryString()
String getHeader(String name)
浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST,请求体中的数据格式如下:
对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:
获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
ServletInputStream getInputStream()
该方法可以获取字节
获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
BufferedReader getReader()
HTTP请求数据中包含了请求行
、请求头
和请求体
,针对这三部分内容,Request对象都提供了对应的API方法来获取对应的值:
对于请求参数的获取,常用的有以下两种:
String getQueryString()
BufferedReader getReader();
但是思考一个问题,GET和POST各自调用各自的函数,而POST函数的代码又和GET的完全一样,代码冗余,如何解决?
要想实现,我们就需要思考:
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,是否可以提供一种统一获取请求参数的方式,从而统一doGet和doPost方法内的代码?
request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可,在request的方法中都实现了哪些操作?
注意:因为参数的值可能是一个,也可能有多个,所以Map的值的类型为String数组。
基于上述理论,request对象为我们提供了如下方法:
Map<String,String[]> getParameterMap()
String[] getParameterValues(String name)
String getParameter(String name)
请求转发(forward):一种在服务器内部的资源跳转方式。
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发
req.getRequestDispatcher("资源B路径").forward(req,resp);
此处主要解决的问题是把请求从资源A
转发到资源B
的时候,如何传递数据给资源B
。
需要使用request对象提供的三个方法:
void setAttribute(String name,Object o);
Object getAttribute(String name);
void removeAttribute(String name);
HTTP响应数据总共分为三部分内容,分别是响应行、响应头、响应体,对于这三部分内容的数据,respone对象都提供了哪些方法来进行设置?
对于响应头,比较常用的就是设置响应状态码:
void setStatus(int sc);
设置响应头键值对:
void setHeader(String name,String value);
对于响应体,是通过字符、字节输出流的方式往浏览器写,
获取字符输出流:
PrintWriter getWriter();
获取字节输出流
ServletOutputStream getOutputStream();
Response重定向(redirect):一种资源跳转方式。
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向
重定向的实现方式:
resp.setStatus(302);
resp.setHeader("location","资源B的访问路径");
//可简写为如下
resp.sendRedirect("资源B的访问路径");
重定向特点:
要想将字符数据写回到浏览器,我们需要两个步骤:
通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();
通过字符输出流写数据: writer.write("aaa");
要想将字节数据写回到浏览器,我们需要两个步骤:
通过Response对象获取字节输出流:ServletOutputStream outputStream = resp.getOutputStream();
通过字节输出流写数据: outputStream.write(字节数据);
JSP = HTML + Java
。我们之前说 JSP 就是一个页面,那么在 JSP 中写 html
标签,我们能理解,但是为什么还可以写 Java
代码呢?
hello.jsp
页面tomcat
会将 hello.jsp
转换为名为 hello_jsp.java
的一个 Servlet
tomcat
再将转换的 servlet
编译成字节码文件 hello_jsp.class
tomcat
会执行该字节码文件,向外提供服务JSP脚本用于在 JSP页面内定义 Java代码。在之前的入门案例中我们就在 JSP 页面定义的 Java 代码就是 JSP 脚本。
JSP 脚本有如下三个分类:
EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。
EL 表达式的主要作用是: 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。
而 EL 表达式的语法也比较简单,$ {expression} 。例如:${brands} 就是获取域中存储的 key 为 brands 的数据。
JavaWeb中有四大域对象,分别是:
el 表达式获取数据,会依次从这4个域中寻找,直到找到为止。而这四个域对象的作用范围如下图所示
例如: ${brands},el 表达式获取数据,会先从page域对象中获取数据,如果没有再到 requet 域对象中获取数据,如果再没有再到 session 域对象中获取,如果还没有才会到 application 中获取数据。
JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码。如下代码就是JSTL标签
男
女
上面代码比起在JSP页面里面直接嵌套Java代码简单并且易懂很多
:相当于 if 判断
男
女
:相当于 for 循环。java中有增强for循环和普通for循环,JSTL 中的
也有两种用法
一种类似于 Java 中的增强for循环。涉及到的
中的属性如下
items:被遍历的容器
var:遍历产生的临时变量
varStatus:遍历状态对象
第二种类似于 Java 中的普通for循环。涉及到的
中的属性如下
begin:开始数
end:结束数
step:步长
从0循环到10,变量名是 i
,每次自增1
${i}
MVC 是一种分层开发的模式,其中:
M:Model,业务模型,处理业务
V:View,视图,界面展示
C:Controller,控制器,处理请求,调用模型和视图
MVC 好处:
职责单一,互不影响。每个角色做它自己的事,各司其职。
有利于分工协作。
有利于组件重用
三层架构是将我们的项目分成了三个层面,分别是 表现层
、业务逻辑层
、数据访问层
。
注册业务功能
,我们会先调用 数据访问层
的 selectByName()
方法判断该用户名是否存在,如果不存在再调用 数据访问层
的 insert()
方法进行数据的添加操作而整个流程是,浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,然后servlet将数据交由 JSP 进行展示。
三层架构的每一层都有特有的包名称:
com.daimalu.controller
或者 com.daimalu.web
com.daimalu.service
com.daimalu.dao
或者 com.daimalu.mapper
如上图上半部分是 MVC 模式,上图下半部分是三层架构。 MVC 模式
中的 C(控制器)和 V(视图)就是 三层架构
中的表现层,而 MVC 模式
中的 M(模型)就是 三层架构
中的 业务逻辑层 和 数据访问层。
可以将 MVC 模式
理解成是一个大的概念,而 三层架构
是对 MVC 模式
实现架构的思想。 那么我们以后按照要求将不同层的代码写在不同的包下,每一层里功能职责做到单一,将来如果将表现层的技术换掉,而业务逻辑层和数据访问层的代码不需要发生变化。
Filter 表示过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。Servlet 前面已经说过了,接下来来了解Filter
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
进行 Filter
开发分成以下三步实现
定义类,实现 Filter接口,并重写其所有方法
配置Filter拦截资源的路径:在类上定义 @WebFilter
注解。而注解的 value
属性值 /*
表示拦截所有的资源
在doFilter方法中输出一句话,并放行
上述代码中的
chain.doFilter(request,response);
就是放行,也就是让其访问本该访问的资源。
拦截路径表示 Filter 会对请求的哪些资源进行拦截,使用 @WebFilter
注解进行配置。如:@WebFilter("拦截路径")
拦截路径有如下四种配置方式:
过滤器链是指在一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。
如下图就是一个过滤器链,我们学习过滤器链主要是学习过滤器链执行的流程
上图中的过滤器链执行是按照以下流程执行:
Filter1
的放行前逻辑代码Filter1
的放行代码Filter2
的放行前逻辑代码Filter2
的放行代码Filter2
的放行后逻辑代码Filter1
的放行后逻辑代码以上流程串起来就像一条链子,故称之为过滤器链。
Listener 表示监听器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
监听器可以监听就是在 application
,session
,request
三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。
request 和 session 我们学习过。而 application
是 ServletContext
类型的对象。
ServletContext
代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。
这里面只有 ServletContextListener
这个监听器后期我们会接触到,ServletContextListener
是用来监听 ServletContext
对象的创建和销毁。
ServletContextListener
接口中有以下两个方法
void contextInitialized(ServletContextEvent sce)
:ServletContext
对象被创建了会自动执行的方法void contextDestroyed(ServletContextEvent sce)
:ServletContext
对象被销毁时会自动执行的方法我们只演示一下 ServletContextListener
监听器
ServletContextListener
接口@WebListener
进行配置代码如下:
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//加载资源
System.out.println("ContextLoaderListener...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//释放资源
}
}
启动服务器,就可以在启动的日志信息中看到 contextInitialized()
方法输出的内容,同时也说明了 ServletContext
对象在服务器启动的时候被创建了。
AJAX
(Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。
我们先来说概念中的 JavaScript
和 XML
,JavaScript
表明该技术和前端相关;XML
是指以此进行数据交换。而这两个之前都讲述过。
AJAX 作用有以下两方面:
异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,等等…
Axios 对原生的AJAX进行封装,简化书写。
Axios官网是:https://www.axios-http.cn
axios 使用是比较简单的,分为以下两步:
引入 axios 的 js 文件
<script src="js/axios-0.18.0.js">script>
使用axios 发送请求,并获取响应结果
发送 get 请求
axios({
method:"get",
url:"http://localhost:8080/ajax-demo1/aJAXDemo1?username=zhangsan"
}).then(function (resp){
alert(resp.data);
})
发送 post 请求
axios({
method:"post",
url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
data:"username=zhangsan"
}).then(function (resp){
alert(resp.data);
});
axios()
是用来发送异步请求的,小括号中使用 js 对象传递请求相关的参数:
method
属性:用来设置请求方式的。取值为 get
或者 post
。url
属性:用来书写请求的资源路径。如果是 get
请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2
。data
属性:作为请求体被发送的数据。也就是说如果是 post
请求的话,数据需要作为 data
属性的值。then()
需要传递一个匿名函数。我们将 then()
中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp
参数是对响应的数据进行封装的对象,通过 resp.data
可以获取到响应的数据。
为了方便起见, Axios 已经为所有支持的请求方法提供了别名。如下:
get
请求 : axios.get(url[,config])
delete
请求 : axios.delete(url[,config])
head
请求 : axios.head(url[,config])
options
请求 : axios.option(url[,config])
post
请求:axios.post(url[,data[,config])
put
请求:axios.put(url[,data[,config])
patch
请求:axios.patch(url[,data[,config])
而我们只关注 get
请求和 post
请求。
8.3.1 基本使用中的 get
请求代码可以改为如下:
axios.get("http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan").then(function (resp) {
alert(resp.data);
});
8.3.1 基本使用中的 post
请求代码可以改为如下:
axios.post("http://localhost:8080/ajax-demo/axiosServlet","username=zhangsan").then(function (resp) {
alert(resp.data);
})
概念:JavaScript Object Notation
。JavaScript 对象表示法.
如下是 JavaScript
对象的定义格式:
{
name:"zhangsan",
age:23,
city:"北京"
}
接下来我们再看看 JSON
的格式:
{
"name":"zhangsan",
"age":23,
"city":"北京"
}
通过上面 js 对象格式和 json 格式进行对比,发现两个格式特别像。只不过 js 对象中的属性名可以使用引号(可以是单引号,也可以是双引号);而 json
格式中的键要求必须使用双引号括起来,这是 json
格式的规定。json
格式的数据有什么作用呢?
作用:由于其语法格式简单,层次结构鲜明,现多用于作为数据载体,在网络中进行数据传输。
JSON
本质就是一个字符串,但是该字符串内容是有一定的格式要求的。 定义格式如下:
var 变量名 = '{"key":value,"key":value,...}';
JSON
串的键要求必须使用双引号括起来,而值根据要表示的类型确定。value 的数据类型分为如下
示例:
var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'
后面我们使用 axios
发送请求时,如果要携带复杂的数据时都会以 JSON
格式进行传递,如下
axios({
method:"post",
url:"http://localhost:8080/ajax-demo/axiosServlet",
data:"username=zhangsan"
}).then(function (resp) {
alert(resp.data);
})
请求参数不可能由我们自己拼接字符串吧?肯定不用,可以提前定义一个 js 对象,用来封装需要提交的参数,然后使用 JSON.stringify(js对象)
转换为 JSON
串,再将该 JSON
串作为 axios
的 data
属性值进行请求参数的提交。如下:
var jsObject = {name:"张三"};
axios({
method:"post",
url:"http://localhost:8080/ajax-demo/axiosServlet",
data: JSON.stringify(jsObject)
}).then(function (resp) {
alert(resp.data);
})
而 axios
是一个很强大的工具。我们只需要将需要提交的参数封装成 js 对象,并将该 js 对象作为 axios
的 data
属性值进行,它会自动将 js 对象转换为 JSON
串进行提交。如下:
var jsObject = {name:"张三"};
axios({
method:"post",
url:"http://localhost:8080/ajax-demo/axiosServlet",
data:jsObject //这里 axios 会将该js对象转换为 json 串的
}).then(function (resp) {
alert(resp.data);
})
注意:
- js 提供的
JSON
对象我们只需要了解一下即可。因为axios
会自动对 js 对象和JSON
串进行想换转换。- 发送异步请求时,如果请求参数是
JSON
格式,那请求方式必须是POST
。因为JSON
串需要放在请求体中。
学习完 json 后,接下来聊聊 json 的作用。以后我们会以 json 格式的数据进行前后端交互。前端发送请求时,如果是复杂的数据就会以 json 提交给后端;而后端如果需要响应一些复杂的数据时,也需要以 json 格式将数据响应回给浏览器。
在后端我们就需要重点学习以下两部分操作:
有一套 API,可以实现上面两部分操作。这套 API 就是 Fastjson
Fastjson
是阿里巴巴提供的一个Java语言编写的高性能功能完善的 JSON
库,是目前Java语言中最快的 JSON
库,可以实现 Java
对象和 JSON
字符串的相互转换。
Fastjson
使用也是比较简单的,分为以下三步完成
导入坐标
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.62version>
dependency>
Java对象转JSON
String jsonStr = JSON.toJSONString(obj);
将 Java 对象转换为 JSON 串,只需要使用 Fastjson
提供的 JSON
类中的 toJSONString()
静态方法即可。
JSON字符串转Java对象
User user = JSON.parseObject(jsonStr, User.class);
将 json 转换为 Java 对象,只需要使用 Fastjson
提供的 JSON
类中的 parseObject()
静态方法即可。