学习和掌握javaWeb
目录
- 基本概念
- 从浏览器到web服务器的“一路”
- Tomcat服务器
- Request&Response
- Request
- 基本概念
- 获取请求数据
- 请求转发
- Response
- 基本概念
- 封装响应数据
- 重定向
- servlet&Filter&Listener
- servlet
- 基本概念
- servlet执行流程
- servlet生命周期
- servlet简化开发or体系结构
- Filter
- 基本概念
- Filter执行流程
- Listener
- 会话跟踪技术
- 基本概念
- cookie
- cookie工作流程
- session
- session工作流程
- session钝化和活化
- Cookie和session区别
- Json
- 基本概念
- Json字符串与java对象的转换
基本概念
-
javaWeb是用java技术解决相关Web互联网领域的技术栈,准确的说是开发网站后端服务程序;
-
目前我们使用APP或者浏览网站应用的通信架构有两种:BS架构和CS架构;BS架构:浏览器-服务器架构,浏览器充当所有BS架构应用的客户端程序,用户操作浏览器向服务器请求数据,服务器根据请求返回响应数据。
-
静态资源是用静态网页技术(Html,CSS,JavaScript)开发的资源,所有用户访问的效果都是一样的,例如文本,图片,音频,视频和Html,CSS,JavaScript都属于静态资源;
-
动态资源,不同用户或者同一个用户访问传递的请求参数不同,服务器返回来的http响应数据经浏览器解析后展现出不一样的效果,那么用户访问的就是动态资源;浏览器访问动态资源时,服务器会先执行动态资源,再将执行的结果转化为静态资源,再发送给浏览器;
从浏览器到web服务器的“一路”
- 用户点击链接或者访问指定网址
- 浏览器通过DNS服务器获取网站主机ip,不指定端口默认端口为80端口,委托操作系统协议栈与web服务器建立tcp链接
- 浏览器依据HTTP协议发送请求数据,服务器接收并解析HTTP请求数据,
- 服务器根据请求行访问的资源路径执行对应的动态资源,查询数据库,然后依据HTTP协议将结果转为响应数据发送给浏览器。
Tomcat服务器
- Web服务器是一个应用程序(软件),对HTTP协议的操作进行封装,使得开发人员不必直接面向协议,简化web应用的开发;简单来说,在javaWeb中,Web服务器就是负责将浏览器发送来的请求数据封装到一个对象里(request),然后把另一个对象(Response)的封装的数据“拿”出来,按照HTTP协议组成响应数据,再发送给浏览器。
- Tomcat是目前用的比较多的轻量级web服务器,也称为Web容器、servlet容器,Servlet(动态资源)只能依据Tomcat才能被调用执行;
- Tomcat默认绑定8080端口,而Http协议默认端口是80,我们可以在Tomcat配置文件中更改Tomcat绑定的端口号;
- 我们将javaWeb项目打包成war包,然后放到Tomcat的webapps磁盘目录下即可部署完成,Tomcat启动时会加载我们部署的war包中的字节码文件,也就是动态资源到jvm方法区,供浏览器访问执行;
- 我们通过idea创建maven web项目,maven会自动将我们的项目打包成war包;
Request&Response
Request
基本概念
当浏览器将http请求数据发送到Tomcat服务器后,Tomcat解析接收到的请求数据,我们知道http请求数据包含请求行、请求头、请求体数据;Tomcat会把这些数据封装到一个Request对象中,实例化绑定目标访问路径的动态资源(比如servlet),执行动态资源对象的方法(比如service),并将该对象引用传递到方法中,程序取出该对象封装的请求数据,执行相应处理;
java提供了request的两个接口,Tomcat实现了这两个接口的实现类。
获取请求数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get......");
//获取请求行数据
req.getMethod(); // GET 获取请求方式
req.getContextPath();///hello_war 获取项目虚拟路径
req.getQueryString();// user=zs 获取get请求方式的请求参数
req.getRequestURI();///hello_war/demo2 获取资源路径
req.getRequestURL();// http://localhost/hello_war/demo2 获取资源全路径
//获取请求头数据
req.getHeader("user-ag")//根据键的名称获取请求头参数值
//获取请求体数据,post方式请求参数会放到请求体中,request提供了字节流和字符流读取请求体数据
BufferedReader br = req.getReader();
String line = br.readLine();
InputStream inputStream = req.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
//我们可以通过设定reques对象解码字符集解决post请求方式的中文乱码问题,post请求方式,
//Tomcat直接将未解码的请求体数据原封不动放到request对象的缓冲区,因此可以设定request
//对象的解码方式,当通过流的方式或者统一方式解码获取缓冲区数据时,不会出现乱码问题
//
request.setCharacterEncoding("UTF-8");
}
- 因为get和post请求方式,请求参数的位置不同,get请求方式,请求参数在请求行中,post请求方式,请求参数在请求体中;
- Tomcat解析请求数据,根据解析到的请求方式,从请求数据中获取请求参数,将其放到request对象的不同数据结构中;我们需要根据请求方式调用不同的方法获取请求参数;
- request提供了统一的API获取请求参数;
//获取封装请求参数的集合对象
Map<String, String[]> map = req.getParameterMap();
//根据键值获取请求参数值数组
String[] hobbies = req.getParameterValues("hobby");
//如果我们知道当前请求参数就一个值,可以用该方法
String userName = req.getParameter("username");
请求转发
请求转发,一种在服务器内部的资源跳转方式;
- 浏览器发送请求数据给服务器,服务器中对应的动态资源A接收到请求;
- 资源A处理完后将请求转发给资源B;
- 资源B处理完委托Tomcat将结果响应给浏览器;
- 请求从资源A到资源B的过程叫请求转发;
Tomcat通过request对象进行请求转发;多个动态资源可以共享request对象封装的数据,包括封装的请求数据和前一个动态资源封装进的数据;
//请求转发,将当前request和response对象传递到下一个动态资源继续处理
req.getRequestDispatcher("资源B绑定路径").forward(req,resp);
req.getRequestDispatcher("/demo2").forward(req,resp);
//request对象可以封装新的数据,再进行请求转发,这样就实现了多个动态资源间数据共享
void setAttribute(String name,Object o);
Object getAttribute(String name);
void removeAttribute(String name);
Response
基本概念
当浏览器将http请求数据发送到Tomcat服务器后,Tomcat除了实例化一个request对象封装请求数据,也会实例化一个空的response对象,然后将response对象传递到动态资源,动态资源将需要响应的数据封装进response对象中,执行完成后,Tomcat从response对象取出数据按照http数据构建成响应数据发送给浏览器
java提供了response的两个接口,Tomcat实现了这两个接口的实现类。
封装响应数据
响应数据包含响应行、响应头、响应体,response对象提供了不同的方法设置这三部分数据
//设置响应行
void setStatus(int sc);
response.setStatus(200);
//设置响应头
void setHeader(String name,String value);
response.setHeader("Location","/request-demo/resp2")
//通过字符流和字节流的方式将数据写到response对象的响应体部分,其中字符流将字符串编码成字节数据后写到response对象的缓冲区,最后Tomcat取出缓冲区数据放到响应数据响应体部分发送给浏览器。
PrintWriter getWriter();
ServletOutputStream getOutputStream();
//response设置响应头content-type字段值为text/html,告诉浏览器响应体的数据是个HTML页面,需要通过HTML解析引擎进行解析,同时设置response的字符输出流的编码字符集为utf8,这样不会出现中文乱码问题,字符输出流按照utf8字符集对字符串编码,放入到response缓冲区冲。
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.write("你好");
writer.write("<h1>aaa</h1>");
重定向
重定向,也是一种资源跳转的方式。
- 浏览器发送请求数据给服务器,服务器中对应的动态资源A接收到请求;
- 资源A无法处理请求,委托Tomcat给浏览器响应一个302的状态码,并在响应头location字段设置可以处理当前请求的访问资源B的路径,资源B的路径可以是服务器内部也可以是服务器外部;
- 浏览器向资源B发出请求数据;
- 资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向
// 设置302状态码,并设置响应头location字段资源B的访问路径
resp.setStatus(302);
resp.setHeader("location","资源B的访问路径");
//简化的重定向方式
resposne.sendRedirect("/request-demo/resp2")
//也可以是服务器外部的资源
resposne.sendRedirect("www.baidu.com")
servlet&Filter&Listener
servlet、Filter、Listener是JavaWeb 三大组件,它们各自承担着不同的职责,共同支撑起一个Web应用的运行。
servlet
基本概念
- servlet 是javaWeb中最重要的动态资源,用于处理浏览器发送的请求数据,并将处理结果委托Tomcat响应给浏览器;
- 当然,servlet 说白了就是个类,但是这个类只能依托Tomcat服务器才能实例化并执行其中的方法,这也就是为什么Tomcat被称为servlet容器;
- 默认情况下,servlet在被浏览器访问时才实例化对象,并执行相应的业务逻辑,并生成动态的web内容;
- servlet的生命周期包含初始化(init)、服务(service)、销毁(destroy)三个阶段
- 我们一般通过注解的方式配置一个类为servlet,实现servlet接口,绑定资源访问路径;
servlet执行流程
- 浏览器发送http请求到Tomcat服务器;
- Tomcat解析请求数据,根据请求行资源访问路径找到目标servlet;
- 将Servlet字节码文件加载到方法区,并实例化出对象,传参Tomcat创建的request和response对象,执行servlet对象的service方法;
- 处理完成委托Tomcat从response对象中取出响应数据,发送给浏览器;
- 处理完成后,servlet对象并不会被销毁,会继续等待处理下一次浏览器请求;
@WebServlet("/demo1") // 绑定/demo1访问路径
public class ServletDemo1 implements Servlet { //需要实现Servlet 接口
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello");
}
@Override
//实例化对象后执行,进行初始化
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init...");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return "";
}
@Override
//被正常销毁时,先执行该方法,再销毁servlet
public void destroy() {
System.out.println("destroy.......");
}
}
servlet生命周期
- 加载和实例化:默认情况下在servlet第一次被访问时由Tomact创建对象
- 初始化:在执行完构造函数实例化对象后,执行init方法,初始化对象
- 请求处理:每次访问servlet时,Tomcat都会调用其service方法进行请求处理
- 销毁:当需要释放内存或者关闭服务器时,Tomcat会调用servlet对象的destroy方法,再释放掉servlet对象
//我们可以再定义servlet类时,通过WebServlet注解的loadOnStartup 属性改变servlet的实例化时机
//负整数表示第一次被访问时才实例化,0或正整数表示Tomcat启动后就实例化对象。
@WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)
public class ServletDemo2 extends HttpServlet {
servlet简化开发or体系结构
- 我们可以实现Servlet接口自己定义servlet类,或者可以继承HttpServlet实体类,然后重写其doGet()和doPost()方法;
- 当浏览器发出请求时,服务器对应的servlet对象会调用HttpServlet的service方法进行处理,该方法会根据request对象获取请求方式,如果是get请求方式就调用其doGet()方法进行处理,如果是post方式,就调用其doPost()方法处理;
@WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)
public class ServletDemo2 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......");
}
}
- 因为request提供了统一的请求参数获取方式,因此,可以继续简化开发方式
@WebServlet(urlPatterns = "/demo3", loadOnStartup = 1)
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String,String[]> paramMap = req.getParameterMap();
String name = req.getParameter("username");
{
//处理请求逻辑
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
Filter
基本概念
- Filter与Servlet类似,也是一个web动态资源,也有三个生命周期方法,但它主要负责拦截请求。Filter可以在请求到达Servlet之前或执行完servlet在响应数据发送给浏览器之前执行一系列操作。
- Filter一般完成一些通用的操作,比如每个资源都要写一些代码完成某个功能,此时我们可以将这部分逻辑开发在filter中,执行完后再执行servlet剩余逻辑;
- 我们一般通过注解的方式配置一个类为Filter,实现Filter接口,绑定拦截的资源路径;
Filter执行流程
- 浏览器发送http请求到Tomcat服务器;
- Tomcat解析请求数据,根据请求行资源访问路径找到目标servlet;
- 在执行servlet之前,Tomcat会实例化拦截该资源路径的filter对象,传参Tomcat创建的request和response对象,执行其doFilter方法;
- 执行前部分逻辑后,doFilter方法内对资源访问放行,将处理后的request和response对象传参目标servlet对象,执行其service方法;
- servlet执行完成后,回到filter,继续执行doFilter方法后面的逻辑;
- 处理完成委托Tomcat从response对象中取出响应数据,发送给浏览器;
//绑定资源拦截路径
@WebFilter(urlPatterns = "/*")
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//实例化对象后执行
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("拦截前逻辑");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("执行完动态资源后的逻辑");
}
@Override
public void destroy() {
//销毁对象之前执行
}
}
Listener
Listener则是用于监听Web应用中的各种事件,如创建、销毁和属性变化等。它可以监听Application、Session和Request对象的生命周期事件。Listener在JavaWeb中的应用相对较少,但在某些场景下仍然非常有用,比如初始化资源或清理资源时。
会话跟踪技术
基本概念
- 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到一方断开连接,会话结束;一次会话包含多次http请求和响应;
- 会话跟踪就是同一个会话多个请求间共享数据,会话跟踪技术就是实现会话跟踪的方式,包括cookie和session;
cookie
cookie:客户端会话跟踪技术,将共享的数据存储在浏览器内存中,以后每次访问都携带cookie数据进行访问;
cookie工作流程
假如服务器端存在两个Servlet,分别是ServletA和ServletB:
- 浏览器发送http请求给服务端,服务端ServletA接收请求并进行业务处理
- ServletA在处理过程中可以创建一个cookie对象,把共享的数据封装到cookie对象中;
- 再将cookie对象封装进response对象;
- ServletA处理完后,Tomcat从response对象中取出cookie封装的共享数据,放到响应数据响应头set-cookie字段中,将响应数据发送给浏览器;
- 浏览器接收到响应数据后,取出set-cookie字段的数据(键值对),存储到内存中,下一次访问同一个服务器时,将cookie数据放到请求行cookie字段中发送给服务器;
- 服务器收到请求数据后,通过request对象的getcookie方法获取共享数据,实现了会话跟踪;
//向浏览器发送cookie
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("username","zs");
cookie.setMaxAge(60*60*24*7); //设置cookie存活时间,可以存储在浏览器磁盘中,不会因为浏览器的关闭而消失
resp.addCookie(cookie);
}
浏览器访问后,我们通过浏览器开发者工具可以看到响应数据包含了set-cookie字段,此时浏览器会把字段值存储到内存中,下一次访问时会把数据放到请求头cookie字段中发给服务器;
此时我们刷新浏览器,再次访问服务器时,可以看到浏览器已经将之前保存的cookie数据放到请求行cookie字段中;
浏览器接收到请求数据后,取出cookie数据封装到cookie对象中,并将cookie对象封装进request对象中,我们通过getCookies()方法获取浏览器发送来的cookie数据;最终实现了会话跟踪;
//
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
String value;
for (Cookie cookie : cookies){
if (cookie.getName() == "username"){
value = cookie.getValue();
}
}
}
session
session:服务器端会话跟踪技术,将共享的数据存储在服务器内存的session对象中,并基于cookie技术实现的会话跟踪方式
session工作流程
假如服务器端存在两个Servlet,分别是ServletA和ServletB:
- 浏览器发送http请求给服务端,服务端ServletA接收请求并进行业务处理
- ServletA在处理过程中可以创建一个session对象,把共享的数据封装到session对象中;
- ServletA处理完后,Tomcat从response对象中取出其他数据放到响应数据中,并将ServletA创建的session对象的id放到响应数据响应头set-cookie字段中,将响应数据发送给浏览器;
- 浏览器接收到响应数据后,取出set-cookie字段的数据(session的id),存储到内存中,下一次访问同一个服务器时,将cookie数据(session的id)放到请求行cookie字段中发送给服务器;
- 服务器收到请求数据后,通过请求数据cookie字段中的session的id,找到服务器维护的session对象,实现了会话跟踪;
//创建request对象获取/创建session对象
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//因为此时request对象维护的cookie数组中没有session id 这一键值对,此时Tomcat会创建一个空的session,
HttpSession session = req.getSession();
session.setAttribute("username","zs");
}
浏览器访问后,我们通过浏览器开发者工具可以看到响应数据包含了set-cookie字段,Tomcat将本次访问创建的session对象的id放到本次响应数据的set-cookie字段中,此时浏览器会把session的id存储到内存中,下一次访问时会把session的id放到请求头cookie字段中发给服务器;
此时我们刷新浏览器,再次访问服务器时,可以看到浏览器已经将之前保存的session的id(cookie数据)放到请求行cookie字段中;
服务器端再次通过request对象就可以获得上一次创建的session对象,其中保存了上一次封装的共享数据,实现了会话跟踪。
//此时Tomcat不会创建一个新的session对象,而是根据request对象封装的cookie数组,遍历找到session id这个cookie,通过该cookie封装的值找到之前已创建的session对象
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Object value = session.getAttribute("username");
}
session钝化和活化
默认情况下,创建的session对象在服务器内存中可以存活30分钟,30分钟后,session对象会被销毁;
- session钝化:30分钟内,服务器正常关闭,服务器会把内存中的session对象序列化保存到服务器磁盘中;
- session活化:启动服务器后,服务器会创建新的session对象,并把磁盘中保存的session数据封装到新的session对象中。
Cookie和session区别
- 存储位置:Cookie 是将数据存储在客户端,Session 将数据存储在服务端
- 安全性:Cookie 不安全,首先本地磁盘数据容易丢失,其次网络传输中可能被别人抓包,相对来说,session更安全;
- 数据大小:Cookie 最大3KB,Session 无限制大小;
- 存储时间:Cookie 可以通过setMaxAge()长期存储,session默认只能存活30分钟,且保存session对象id的cookie数据只能存储在浏览器的内存中,不能设置存活时间长期存储,浏览器关闭再打开后,保存的session id的cookie数据会丢失;
- 服务器性能:Cookie 不占服务器资源,Session占用服务器资源。
Json
基本概念
- json是一种数据格式,全称JavaScript Object Notation:JavaScript 对象表示法;
- 由于json数据格式简单,层次结构鲜明,现多用于浏览器和服务器数据传输的载体,在网络中进行数据传输;
- json本质上就是符合一种标准或者格式的字符串,json字符串可以放在请求数据请求体部分发送给web服务器,请求体中不仅可以是常规的请求参数,也可以是json格式的数据;同时也可由web服务器放在响应体中发送给浏览器;
//一个标准的json数据
{
"name":"zhangsan",
"age":23,
"city":"北京"
}
//其中键必须是双引号,值有多种类型
数字(整数或浮点数)
字符串(使用双引号括起来)
逻辑值(true或者false)
数组(在方括号中)
对象(在花括号中)
null
4.json数据不一定非要用大括号{},{}是json的对象格式,json的简单类型数据不需要用大括号
下面都是json数据
["1","2","3"]
true
3.14
Json字符串与java对象的转换
- 请求数据:JSON字符串转为Java对象;浏览器发送的请求数据中的json数据一般会被web服务器封装到一个java对象中进行操作,对象的属性对应json数据的键,对象属性值对应着json数据的值;
User u = JSON.parseObject("
{\"id\":1,\"password\":\"123\",\"username\":\"zhangsan\"}", User.class);
响应数据:Java对象转为JSON字符串,服务器将java对象转换成json字符串后发送给浏览器;
User user = new User();
user.setId(1);
user.setUsername("zhangsan");
user.setPassword("123");
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);//{"id":1,"password":"123","username":"zhangsan"}