目录
前端基础介绍
随着网络技术的不断发展,单机的软件程序不足以满足网络计算的需求。为此,各种各样的网络程序开发体系结构应运而生,这当中,运用最多的网络应用程序开发体系结构主要分为两种:一种是基于浏览器/服务器的B/S结构;另外一种是基于客户端/服务器的C/S结构。
C/S结构
(1)C/S(Client/Server,客户端/服务器)体系结构由美国Borland公司最早研发。
(2)特点:必须在客户端(用户设备上)安装特定的软件。
(3)优点:图像效果显示比较好(比如:3D游戏)。
(4)缺点:服务器的软件和功能进行升级,客户端也必须升级,否则使用不了新的功能,不利于维护。
(5)常见的C/S体系结构程序:QQ、微信等。
B/S结构
(1)B/S(Bowser/Server,浏览器/服务器)体系结构由美国微软公司研发。
(2)特点:只需要一个浏览器通过http协议就可以访问,不需要在客户端(用户设备上)安装特定的软件。
(3)优点:服务功能的升级只需要升级服务器端,浏览器中不需要做任何升级操作。
(4)缺点:图形显示效果不如C/S体系结构。
(5)常见的B/S体系结构:淘宝、京东、支付宝等。
web服务器
Web服务器是发布Web应用、运行Web应用的容器。只有将开发好的Web项目部署在Web服务器中,才能使网络中的用户通过浏览器来访问Web应用。Web服务器的主要功能就是提供网上信息浏览服务。(将Web服务器理解成存储数据(项目)的容器)
开源的Web服务器: 1)Tomcat(主流Web服务器之一,非常适合初学者学习)。 2)jetty(淘宝使用,运行效率比Tomcat高)。 3)resin(新浪使用,所有开源服务器软件中,运行效率最高的)。 上面三个的用法从代码角度看完全相同,只是在开启、关闭服务软件时用的命令稍微有点区别。 收费的Web服务器: 1)WebLogic,Oracle公司开发的。 2)WebSphere,IBM公司开发的。 收费的Web服务器提供相应的服务与支持,软件比较大,资源消耗大。
Tomcat服务器
Tomcat是一个运行Servlet和JSP Web应用软件。基于Java的Web应用软件容器。Tomcat Server是根据Servlet和JSP规范运行的,因此可以说Tomcat Server也实行了Apache规范,且比绝大多数商业应用软件服务器要好。
tomcat安装配置:
官网下载(和jdk版本对应,jdk17对应tomcat10),安装,配置环境变量CATLINA_HOME:安装路径、path:%CATALINA_HOME%\bin
文件夹 | 作用 | 说明 |
---|---|---|
bin | 存放启动和关闭Tomcat的可执行脚本文件 | startup.bat启动Tomcat shutdown.bat停止Tomcat |
conf | 存放Tomact服务器的各种配置文件 | 这是一个非常重要的目录,这个目录下的server.xml文件和web.xml文件最重要。 server.xml:配置整个服务器信息,例如修改端口号,设置编码格式等。 web.xml:项目部署描述文件,这个文件中注册了很多MIME类型,即文档类型 |
lib | 存放Tomcat服务器的支撑jar包 | Tomcat的类库,里面存放Tomcat运行时所需要的jar文件 |
logs | 存放Tomcat的日志文件 | 该文件中记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,异常也会记录在日志文件中 |
temp | 存放Tomcat运行时产生的临时文件 | 这个目录下的东西在停止Tomcat后删除 |
webapps | 存放各种Web应用 | 存放Web项目的目录,其中每个文件夹都是一个项目,其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。 |
work | Tomcat的工作目录 | 运行时生成的文件,最终运行的文件都在这个文件夹中。当客户端用户访问一个jsp文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java文件和class文件都会存放在这个目录下 |
HTTP协议
HTTP(HyperText Transfer Protocol),超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个基于请求与响应模式的、无状态的、应用层的协议,运行于TCP协议基础之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。
HTTP是基于客户/服务器模式,且面向连接的。典型的HTTP事务处理有如下的过程:
(1)客户端与服务器建立连接(三次握手)。
(2)客户向服务器发送请求。
(3)服务器接受请求,并根据请求返回响应的文件作为应答。
(4)客户与服务器关闭连接(四次挥手)。
状态代码 | 状态描述 | 说明 |
---|---|---|
200 | OK | 客户端请求成功 |
302 | Found | 临时重定向 |
403 | Forbidden | 服务器收到请求,但是拒绝提供服务。 服务器通常会在响应正文中给出不提供服务的原因 |
404 | Not Found | 请求的资源不存在,最常见的就是输入了错误的路径 |
500 | Internal Server Error | 服务器发生不可预期的错误,导致无法完成客户端的请求 |
Javaweb三大组件
JavaWeb三大组件指的是:Servlet 程序、Filter 过滤器、Listener 监听器,它们在JavaWeb开发中分别提供不同的功能。
三大组件初始化顺序
- Listener
- Filter
- Servlet
销毁顺序:
- 先销毁 Servlet;
- Filter
- Listener
Servlet
概念
(1)Servlet:Server Applet的简称,是运行在Web服务器端的Java程序,可交互式的处理客户端发送到服务器端的请求,并完成响应操作,它使用Java语言编写(Servlet是Java代码)。
(2)Servlet可实现动态网页。
(3)Servlet是JavaWeb开发程序的基础,是一个标准,由SUN定义,具体细节由Servlet容器进行实现,如Tomact、JBoss等。Servlet是JavaEE规范(一套接口)的一个组成部分。
作用:
(1)接收客户端请求,完成相关操作
(2)动态生成网页(页面数据可变,不同用户页面数据不同)
(3)将包含操作结果的动态网页响应给客户端。
idea创建servlet项目:
1.创建普通java项目。2.项目右键Add framework support->web application。3.在edit configurations里配置(基本不用改),在deployment里部署->点击加号配置war包。URL和Application context是路径,可以修改。如果idea里使用的是UTF-8,必须在VM options里添加: -Dfile.encoding=UTF-8,如果不是不用改(Settings->editor->File Encodings里查看).4.在WEB-INF里创建lib包存放jar包,(tomcat 10用jakarta包,10以前用javax包)jar包位置有要求,不放在这里不行
搭建开发环境
将Tomcat安装路径下lib文件夹中与Servlet相关的jar包(lib\servlet-api.jar)配置到classpath环境变量中。在web.xml里添加servlet节点(可用注解@WebServlet("/路径名")代替,在servlet类名上使用)
<!-- 1、添加Servlet节点-->
<servlet>
<!-- 你的Servlet类名称-->
<servlet-name>MyFirstServlet</servlet-name>
<!-- 你的Servlet类的完整路径-->
<servlet-class>com.xxx.servlet01.ServletDemo01</servlet-class>
</servlet>
<!-- 2、 添加servlet-mapping节点-->
<servlet-mapping>
<!-- 这个地方的servlet-name值要和上面servlet-name值保持一致-->
<servlet-name>MyFirstServlet</servlet-name>
<!-- url-patter配置的内容是浏览器地址栏中URL里项目名称后的资源内容-->
<url-pattern>/firstServlet</url-pattern>
</servlet-mapping>
web.xml的部分节点含义:
url-pattern定义匹配规则,取值说明:
精确匹配 /具体的名称 只有url路径是具体的名称的时候才会触发Servlet
后缀匹配 *.xxx 只要是以xxx结尾的就匹配触发Servlet
通配符匹配 /* 匹配所有请求,包含服务器的所有资源
通配符匹配 / 匹配所有请求,包含服务器的所有资源,不包括.jsp
load-on-startup
1)元素标记容器是否应该在web应用程序启动的时候就加载这个servlet。
2)它的值必须是一个整数,表示servlet被加载的先后顺序。
3)如果该元素的值为负数或者没有设置,则容器会当servlet被请求时再加载。
4)如果值为整数或0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
注解属性:
-
name:Servlet名字(可选)
-
value:配置url路径,可以配置多个
-
urlPatterns:配置url路径,和value作用一样,不能同时使用
-
loadOnStartup:配置Servlet的创建的时机,如果是0或者正数,启动程序时创建,如果是负数,则访问时创建。数字越小优先级越高。
之后编写servlet类即可运行测试
Servlet的生命周期
实例化、初始化、服务、销毁
当用户第一次访问Servlet时,由容器调用Servlet的构造器创建具体的Servlet对象。也可以在容器启动之后立刻创建实例。
实例化只执行一次、 init()实例化只执行一次、 service()方法会执行多次、destroy()方法执行一次
Servlet类编写
在Servlet API中最重要的是Servlet接口,所有Servlet都会直接或间接的与该接口发生联系,或是直接实现该接口,或间接继承自实现了该接口的类。该接口中包括以下5个方法: destroy()、
ServletConfig getServletConfig()、String getServletInfo()、void init(ServletConfig arg0)、
void service(ServletRequest arg0, ServletResponse arg1)
三种Servlet类实现方式
1.实现Servlet接口、2.继承GenericServlet、3.继承HttpServlet类(常用)
实现Servlet接口一般重写service方法,GenericServlet一样
HTTPServlet的子类至少必须重写一个方法,通常是前两个:
-
doGet():用于HTTP GET请求
-
doPost():用于HTTP POST请求
-
doPut():用于HTTP PUT请求
-
doDelete():用于HTTP DELETE请求
Servlet线程安全:
-
synchronize
将存在线程安全问题的代码放到同步代码块中 -
实现SingleThreadModel接口
servlet实现SingleThreadMode接口后。每个线程都会创建servlet实例,这样每个客户端请求就不存在共享资源的问题,但是servlet响应客户端的效率太低,所以已经淘汰。 -
尽可能使用局部变量
Servlet对象
在接收到客户端请求时,Servlet 容器会创建以下对象:
- HttpServletRequest 对象:封装了客户端请求的信息,包括请求参数、请求头、请求体等信息。
- HttpServletResponse 对象:封装了响应信息,包括响应状态码、响应头、响应体等信息。
- ServletContext 对象:代表 Servlet 上下文,可以用于在不同 Servlet 之间共享数据。
- HttpSession 对象:代表客户端的会话,可以用于在同一客户端多次请求之间共享数据。
- ServletConfig 对象:代表 Servlet 的配置信息,包括 Servlet 的初始化参数等信息。
- ServletRequest 对象:是 HttpServletRequest 的父接口,定义了通用的请求方法,如获取请求参数等。
- ServletResponse 对象:是 HttpServletResponse 的父接口,定义了通用的响应方法,如设置响应头等。
以上对象都是由 Servlet 容器在接收到客户端请求时创建的,可以在 Servlet 中直接使用。其中,HttpServletRequest 和 HttpServletResponse 对象是每个请求独有的,而 ServletContext 和 HttpSession 对象则是在多个请求之间共享的。
ServletConfig
Servlet程序的配置信息类
在Servlet 程序创建时,就会创建一个对应的 ServletConfig 对象。
它的三大作用:
- 获取web.xml 中 Servlet 程序的别名 servlet-name 的值
- 获取web.xml 中 Servlet 程序的获取初始化参数 init-param
- 获取 ServletContext 对象
ServletContext
Servlet上下文接口
- 每个web项目只有一个ServletContext对象,在web工程部署启动的时候创建,在工程停止的时候关闭。
- ServletContext 对象是一个域对象(可以像Map一样存储数据的对象。域指的是作用域,这里是整个web工程)。
ServletContext 类的四个作用:
- 获取 web.xml 中配置的上下文参数 context-param
- getContextPath()获取当前的工程路径,格式: /工程路径
- getRealPath()获取工程部署后在服务器硬盘上的绝对路径
- 像 Map 一样存取数据
请求/响应数据
流程图:
get和post区别
get和post是两种主要的提交方法
get请求
-
get提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连
-
get方式明文传递,数据量小,不安全
-
效率高,浏览器默认请求方式为get请求
-
对应的Servlet的方法是doGet()
post请求
-
post方法是把提交的数据放在HTTP包的body中
-
密文传递数据,数据量大,安全
-
效率没有get高
-
对应的Servlet的方法是doPost()
ServletRequest
ServletRequest接口是Java Servlet API中的一个接口,用于访问Servlet容器接收到的HTTP请求的信息。ServletRequest接口定义了一系列方法,用于获取HTTP请求的参数、属性、输入流等信息,以及对这些信息的操作。以下是ServletRequest接口中的一些常见的方法:
方法 | 说明 |
getParameter(String name) | 返回请求参数的值,如果请求参数不存在,则返回null |
getAttribute(String name) | 返回指定属性名称的属性值,如果属性不存在,则返回null |
setAttribute(String name, Object value) | 将指定属性名称的属性值设置为指定的值 |
getSession() | 返回与此请求相关联的会话,如果请求没有会话则创建一个新会话 |
在实际开发中,我们通常会使用HttpServletRequest接口,它继承了ServletRequest接口,并增加了更多HTTP特定的请求和响应信息的方法。
HttpServletRequest
在 Servlet API 中,定义了一个 HttpServletRequest 接口,它继承自 ServletRequest 接口。HttpServletRequest 专门用于封装 HTTP 请求消息,该接口在ServletRequest接口的基础上增加了许多HTTP特定的方法,以提供更多的HTTP请求和响应相关的信息
方法 | 说明 |
---|---|
getMethod() | 该方法用于获取 HTTP 请求方式(如 GET、POST 等)。 |
getRequestURI() | 该方法用于获取请求行中的资源名称部分(位于 URL 的主机和端口之后,参数部分之前的部分)。 |
getRequestURL() | 返回HTTP请求的统一资源定位器(URL) |
getQueryString() | 该方法用于获取请求行中的参数部分,也就是 URL 中“?”以后的所有内容。 |
getContextPath() | 返回当前 Servlet 所在的应用的名字(上下文)。对于默认(ROOT)上下文中的 Servlet,此方法返回空字符串""。 |
getServletPath() | 该方法用于获取 Servlet 所映射的路径。 |
getRemoteAddr() | 该方法用于获取客户端的 IP 地址。 |
getRemoteHost() | 该方法用于获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则该方法将会返回客户端的 IP 地址。 |
getPathInfo() | 返回HTTP请求的路径信息 |
getServletPath() | 返回HTTP请求的Servlet路径 |
getHeader(String name) | 该方法用于获取一个指定头字段的值,如果请求消息中包含多个指定名称的头字段,则该方法返回其中第一个头字段的值 |
getParameter(String name) | 返回指定参数名的参数值。 |
getParameterValues (String name) | 以字符串数组的形式返回指定参数名的所有参数值(HTTP 请求中可以有多个相同参数名的参数)。 |
request
一次请求,所谓的Request(在JSP中使用的)其实只是规范中的一个名称而已。
它当然是一个对象,但并不是SUN提供的,这是由各个不同的Servlet提供商编写的,SUN只是规定这个类要实现HttpServletRequest接口,并且规定了各个方法的用途,但具体是什么类是由各个提供商自己决定的。
浏览器会发送HTTP请求到后台服务器(Tomcat)。HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]。后台服务器会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数。获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
常用方法:
方法名 | 方法说明 |
---|---|
String getParameter(String name) | 根据表单组件名称获取提交的数据 |
void setCharacterEncoding(String charset) | 指定每个请求的编码 |
setAttribute(key,value) | 设置属性 |
getAttribute(key) | 获取属性 |
response
业务处理完后,后台就需要给前端返回业务处理的结果即响应数据。把响应数据封装到response对象中。后台服务器会解析response对象,按照[响应行+响应头+响应体]格式拼接结果。浏览器最终解析结果,把内容展示在浏览器给用户浏览。
常用方法:
方法名称 | 方法作用 |
---|---|
setHeader(name,value) | 设置响应信息头 |
setContenType(String) | 设置响应文件类型、响应式的编码格式 |
setCharacterEncoding(String) | 设置服务端响应内容编码格式 |
getWriter() | 获取字符输出流 |
中文乱码问题
get乱码:get请求发送后,在服务器端获取中文数据产生乱码,是因为服务器和客户端沟通的编码不一致造成的,所以解决办法是在客户端和服务器之间设置一个统一的编码,之后就按照设置的编码进行数据的传输和接收。
此外,在Tomcat7及以下版本,客户端以UTF-8的编码传输数据到服务器端,而服务器端的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致,因此会产生中文乱码。
(1)解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题。
(2)Tomcat8的版本中get不会出现乱码了,因为服务器对url的编码格式可以自动转换。
post乱码:由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器端也需要设置以UTF-8字符编码进行接收。
解决方法:使用从ServletRequest接口继承而来的setCharacterEncoding(charset)方法进行统一的编码设置。
由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器端也需要设置以UTF-8字符编码进行接收。
request乱码:解决方法:使用从ServletRequest接口继承而来的setCharacterEncoding(charset)方法进行统一的编码设置。
/设置请求参数的编码格式,这种方式对get请求方式无效
req.setCharacterEncoding("UTF-8");
response乱码:如果输出内容包含中文,则出现乱码,因为服务器默认采用ISO8859-1编码响应内容。
方式一:设置服务器端响应的编码格式和设置客户端响应内容的头内容的文件类型及编码格式,这种方式不推荐
resp.setCharacterEncoding("UTF-8");
resp.setHeader("Content-type","text/html;charset=UTF-8");
方式二:同时设置服务端的编码格式和客户端响应的文件类型及响应时的编码格式,推荐此方式
//设置响应编码格式UTF-8
resp.setContentType("text/html;charset=UTF-8");
转发和重定向
转发:的作用在服务器端,地址栏不变,将请求发送给服务器上的其它资源,以共同完成一次请求的处理。req.getRequestDispatcher("路径").forward(req,resp);
forward表示一次请求,是在服务器内部跳转,可以共享同一次request作用域中的数据。
-
request作用域:拥有存储数据的空间,作用范围是一次请求有效(一次请求可以多次转发)
可以将数据存入request后,在一次请求过程中的任何位置进行获取可传递任何数据类型(基本数据类型、对象、数组、集合等) -
存数据:request.setAttribute(key,value);
以键值对形式存储在request作用域中。key为String类型,value为Object类型 -
取数据:request.getAttribute(key);
通过String类型的key获取Object类型的value
重定向:作用在客户端,客户端将请求发送给服务器中,服务器响应给客户端一个新的请求地址,客户端重新发送新请求。使用redirect跳转时,是在客户端跳转,地址栏发生变化,属于多次请求重定向传值只能在路径后面resp.sendRedirect("路径?username=" + URLEncoder.encode(username, "UTF-8") + "&password=" + password + "");
浏览器使用:需要加虚拟目录(项目访问路径)
服务端使用:不需要加虚拟目录
对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录,只需写@WebSevlet的值
对于重定向来说,路径最终是由浏览器来发送请求,就需要添加虚拟目录。
Cookie
Cookie是浏览器提供持久化存储数据的机制,在浏览器访问Web服务器的某个资源时,由Web服务器在HTTP响应消息头中附带传送给浏览器的一小段数据。一旦Web浏览器保存了某个Cookie,那么它在以后每次访问该Web服务器时,都应在HTTP请求头中将这个Cookie回传给Web服务器。一个Cookie主要有标识该信息的名称(name)和值(value)组成。
Cookie存储在浏览器(客户端) 所在主机的硬盘中,当用户访问网站生成Cookie时,它会在用户的计算机上创建一个文本文件,并将其存储在浏览器的Cookie存储区域中(该文件在客户端硬盘上),浏览器会定期清理Cookie存储区域,以删除过期的Cookie。
通过java代码设置获取Cookie
//设置Cookie
Cookie cookie = new Cookie("username", "zhangsan");
/*
*设置Cookie存活时间,在浏览器内存中的保存时间,单位为秒,
* 正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
* 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
* 零:删除对应Cookie
*/
cookie.setMaxAge(60);
//设置Cookie的访问路径
cookie.setPath("/GetCookieValueServlet");
//发送Cookie到客户端
response.addCookie(cookie);
//-------------------------------------------------------------
//获取所有Cookie
Cookie[] cookies = request.getCookies();
//遍历数组,获取所有的Cookie
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + "-" + cookie.getValue());
}
System.out.println("----------------------------------------");
//遍历数组,获取指定的Cookie
for (Cookie cookie : cookies) {
if (cookie.getName().equals("username")) {
System.out.println(cookie.getName() + "-" + cookie.getValue());
}
}
//-------------------------------------------------------------
//设置Cookie,如果改变cookie的name和有效路径,会新建cookie,而改变cookie值、有效期会覆盖原由的cookie
Cookie cookie = new Cookie("username", "lisi");
/*
*设置Cookie存活时间,在浏览器内存中的保存时间,单位为秒,
* 正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
* 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
* 零:删除对应Cookie
*/
cookie.setMaxAge(30);
//设置Cookie的访问路径
cookie.setPath("/webProject09_war_exploded/GetCookieValueServlet01");
//发送Cookie到客户端
response.addCookie(cookie);
浏览器查看Cookie
1.f12->Network,2.设置->隐私与安全
Cookie默认不支持中文,只能包含ASCII字符,所以Cookie需要对Unicode字符进行编码,否则会出现乱码
-
编码可以使用java.net.URLEncoder类的encode(String str,String encoding)方法
-
解码可以使用java.net.URLDecoder类的decode(String str,String encoding)方法
//创建中文Cookie
//设置请求参数的编码格式,这种方式对get请求方式无效
request.setCharacterEncoding("UTF-8");
//设置响应编码格式为UTF-8
response.setContentType("text/html;charset=UTF-8");
//Cookie默认不支持中文,只能包含ASCII字符,所以Cookie需要对Unicode字符进行编码,否则会出现乱码
Cookie cookie = new Cookie(URLEncoder.encode("姓名","UTF-8"),URLEncoder.encode("张三","UTF-8"));
//设置Cookie的访问路径
cookie.setPath("/webProject09_war_exploded/GetCookieValueServlet04");
//发送Cookie到客户端
response.addCookie(cookie);
//----------------------------------------------------------------
//读取中文Cookie
//设置请求参数的编码格式,这种方式对get请求方式无效
request.setCharacterEncoding("UTF-8");
//设置响应编码格式为UTF-8
response.setContentType("text/html;charset=UTF-8");
//获取所有Cookie
Cookie[] cookies = request.getCookies();
//遍历数组,获取指定的Cookie
for (Cookie cookie : cookies) {
if (URLDecoder.decode(cookie.getName(),"UTF-8").equals("姓名")) {
System.out.println(URLDecoder.decode(cookie.getName(),"UTF-8") + "-" + URLDecoder.decode(cookie.getValue(),"UTF-8"));
}
}
Cookie优点
-
可配置到期规则
-
简单性:Cookie是一种基于文本的轻量结构,包含简单的键值对
-
数据持久性:Cookie默认在过期之前是可以一直存在客户端浏览器上的
Cookie缺点
-
大小受到限制:大多数浏览器对Cookie的大小有4K、8K字节的限制
-
用户配置为禁用:有些用户禁用了浏览器或客户端设备接收Cookie的能力,因此限制了这一功能
-
潜在的安全风险:Cookie可能会被篡改。会对安全性造成潜在风险或者导致依赖于Cookie的应用程序失败
Session
概述
Session存在于服务器端,是SessionId和对应的HttpSession对象的键值对结构。同时HttpSession对象中可以存储程序员自定义的键值对。
(1)Session用于记录用户的状态。Session指的是一段时间内,单个客户端与Web服务器的一连串相关的交互过程。
(2)在一个Session中,客户可能会多次请求访问同一个资源,也有可能请求访问各种不同的服务器资源。
(3)Session是由服务器端创建的
特点
(1)Session会为每一次会话分配一个Session对象
(2)同一个浏览器发起的多次请求,同属于一次会话(Session)
(3)首次使用到Session时,服务器会自动创建Session,并创建Cookie存储SessionId发送回客户端
作用域
-
一次会话是使用同一浏览器发送的多次请求。一旦浏览器关闭,则结束会话
-
可以将数据存入Session中,在一次会话的任意位置进行获取
-
可传递任何数据(基本数据类型、对象、集合、数组)
-
浏览器关闭/浏览器关闭,则失效
获取Session
Session是服务器端自动创建的,通过request对象获取
//设置请求参数的编码格式,这种方式对get请求方式无效
request.setCharacterEncoding("UTF-8");
//设置响应编码格式为UTF-8
response.setContentType("text/html;charset=UTF-8");
//获取Session对象,首次使用到Session时,服务器会自动创建Session,并创建Cookie存储SessionId发送回客户端
HttpSession session = request.getSession();
System.out.println("ID:" + session.getId());//唯一标记
使用setArrtibute(属性名,Object)保存数据到session中
//获取Session对象,首次使用到Session时,服务器会自动创建Session,并创建Cookie存储SessionId发送回客户端
HttpSession session = request.getSession();
//将数据存储以键值对的形式到session对象中,可传递任何数据(基本数据类型、对象、集合、数组)
session.setAttribute("username","张三");
使用getAttribute("属性名");获取session中数据。
//获取Session对象
HttpSession session = request.getSession();
//获取session对象中的值,获取的值是Object类型,转换为其对应的类型
String username = (String) session.getAttribute("username");
System.out.println("session对象中存储的username值:" + username);
使用removeAttribute移除Session数据
//获取Session对象,首次使用到Session时,服务器会自动创建Session,并创建Cookie存储SessionId发送回客户端
HttpSession session = request.getSession();
//通过键移除session作用域中的值
session.removeAttribute("username");
session.invalidate();//登录退出,销毁
Session与Request应用区别
(1)request是一次请求有效,请求改变,则request改变
(2)session是一次会话有效,浏览器改变,则session改变
Cookie禁用
务器在默认情况下,会使用Cookie的方式将sessionID发送给浏览器,如果用户禁止Cookie,则sessionID不会被浏览器保存,此时,服务器可以使用URL重写这样的方式来发送sessionID
//获取Session对象
HttpSession session = request.getSession();
//输出sessionid值
System.out.println("GetSessionValueServlet类中输出ID:"+session.getId());
//重写URL追加session值
String newURL = response.encodeURL("/GetSessionValueServlet01");
System.out.println("重写后的URL:"+newURL);
//重定向
response.sendRedirect(newURL);
ServletContext
概述
(1)全局对象,也拥有作用域,对应一个Tomcat中的Web应用
(2)当Web服务器启动时,会为每一个Web应用程序创建一块共享的存储区域(ServletContext)
(3)ServletContext在Web服务器启动时创建,服务器关闭时销毁
三种方式获取ServletContext对象
-
GenericServlet提供了getServletContext(()方法。推荐使用this.getServletContext();
-
HttpServletRequest提供了getServletContext()方法。推荐使用
-
HttpSession提供了getServletContext()方法。
作用
获取当前项目在服务器发布的真实路径(盘符路径)
获取当前项目上下文路径(项目名)
全局容器(ServletContext拥有作用域,可以存储数据到全局容器中 )
-
存储数据:servletContext.setAttribute("name",value);
-
获取数据:servletContext.getAttribute("name");
-
移除数据:servletContext.removeAttribute("name");
特点
-
唯一性:一个应用对应一个ServletContext
-
生命周期:只要tomcat不关闭或者应用不卸载,ServletContext就一直存在
三种容器作用域总结
-
HttpServletRequest:一次请求,请求响应之前有效
-
HttpSession:一次会话开始,浏览器不关闭或不超时之前有效
-
ServletContext:服务启动开始,服务器停止之前有效
监听器
Javaweb三大组件之一,Listener表示服务器的事件监听器,用于监听三个域对象的状态(对象、对象的属性)变化,三个域对象分别是:ServletContext、HttpSession、HttpServletRequest。
分别对应的监听类是:
1.ServletContextListener、ServletContextAttributeListener;
2.HttpSessionListener、HttpSessionActivationListener、HttpSessionBindingListener、HttpSessionAttributeListener;
3.ServletRequestListener、ServletRequestListener
也可依据功能划分:
第一类:监听容器本身的创建和销毁
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
第二类:监听容器的内容变化
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletRequestAttributeListener
第三类:专门针对Javabean的,让Javabean实现接口重写方法即可
- HttpSessionBindingListener
- HttpSessionActivationListener
使用
1.定义类,实现ServletContextListener接口
2.可在web.xml配置或使用注解 @WebListener配置
过滤器
三大组件之一,作用是:拦截请求,过滤响应。
应用场景
- 权限检查
- 日记操作
- 事务管理
使用步骤
1、实现 Filter 接口,实现过滤方法 doFilter()
2、到 web.xml 中去配置 Filter 的拦截路径
生命周期
- 构造器方法
- init 初始化方法
- doFilter 过滤方法
- destroy 销毁
第 1,2 步初始化,在 web 工程启动的时候执行(Filter 已经创建);第 3 步 每拦截到一次请求,就会执行一次;第 4 步 停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)。
- filter 在 web 项目启动时, 由 tomcat 来创建 filter 实例, 只会创建一个
- 会调用 filter 默认的无参构造器, 同时会调用 init 方法, 只会调用一次
- 在创建 filter 实例时,同时会创建一个 FilterConfig 对象,并通过 init 方法传入
- 通过 FilterConfig 对象,程序员可以获取该 filter 的相关配置信息
- 当一个 http 请求和该 filter 的的 url-patter 匹配时,就会调用 doFilter 方法
- 在调用 doFilter 方法时, tomcat 会同时创建 ServletRequest 和 ServletResponse 和 FilterChain 对象并通过 doFilter 传入.
- 如果后面的请求目标资源(jsp,servlet…) 会使用到 request,和 response,那么会继续传递
FilterConfig
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。
FilterConfig 类的作用是获取 filter 过滤器的配置内容:
- 获取 Filter 的名称 filter-name 的内容
- 获取在 Filter 中配置的 init-param 初始化参数
- 获取 ServletContext 对象
拦截路径匹配规则
- 精确匹配 /target.jsp
- 目录匹配 /admin/*
- 后缀名匹配 *.html
Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在
过滤器过滤的是URI的请求
所以如果是请求转发的话,URI是没有变化的。
也就是说没有发起一次新的请求,所以不会再重新经过过滤器。
配置多个过滤器
在多个Filter执行的时候,它们执行的优先顺序由它们在web.xml中从上到下配置的filter-mapping顺序决定,与filter的配置顺序无关。
执行顺序
Http请求 -> A 过滤器 dofilter() -> A 过滤器前置代码 -> A 过滤器 chain.doFilter() -> B 过滤器 dofilter() -> B 过滤器前置代 码 -> B过滤器 chain.doFilter() -> 目标文件 -> B过滤器后置代码 -> A过滤器后置代码 -> 返回给浏览器页面/数据
- 所有Filter和目标资源默认都执行在同一个线程中
- 多个Filter共同执行的时候,它们都使用同一个Request对象(假如Filter1的request对象设置了一个属性,Filter2也能获取出来)
拦截器
拦截器方法都是通过代理的方式来调用的,是基于反射机制实现的,依赖于web框架
java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。在AOP中,拦截器用于在某个方法或者字段被访问之前,进行拦截然后再之前或者之后加入某些操作。
spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor。HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。
HandlerInterceptor
步骤
- 实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。
- 在springMVC配置文件中配置拦截器
HandlerInterceptor接口中的3个方法:
- preHandler():该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作。
- postHandle():该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
- afterCompletion():该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
MethodInterceptor
MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。
步骤
- 实现MethodInterceptor接口,或利用AspectJ的注解
- 在spring配置文件中配置
拦截器与过滤器区别
- filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于java本身的反射机制,这是两者最本质的区别。
- 过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。
- Filter的过滤范围比Interceptor大,Filter除了过滤请求外通过通配符可以保护页面,图片,文件等等,而Interceptor只能过滤请求。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。