目录
1.web相关概念
1.1 软件的基本架构
C/S(Client-Server),比如我们手机上的app QQ 微信
特点:必须下载特定的客户端程序。服务端升级之后,客户端也需要随着升级。
B/S(Broswer-Server),比如京东网站,腾讯qq官方网站
特点:只需要安装浏览器就可以访问。如果服务器端升级了,浏览器端不需要随之升级。
JavaWeb开发,开发的软件是基于B/S的软件架构。
1.2 资源
资源就是用户想要获取的资源。资源分为两种,一种是静态资源,一种是动态资源。
静态资源是不会经常发生变化的资源,比如HTML CSS JS 图片。
动态资源是会发生变化的资源,比如servlet jsp。如果我们想要获取动态资源,这些动态资源必须通过服务器部署之后才能获取。
1.3 tomcat
服务器的种类有很多,有文件服务器、邮件服务器、web服务器、数据库服务器。我们的动态资源是部署在web服务器上的,web服务器接收到http请求之后把请求交给Servlet来处理,调⽤业务类实现动态资源获取。
web服务器有很多,比如tomcat、jetty、weblogic,jboss。
1.3.1 tomcat是什么
Tomcat是一个免费的开放源代码的Web应用服务器,是Apache软件基金会项目中的一个核心项目,由Apache ,Sun共同开发而成,深受Java爱好者的喜爱,是一款比较流行的web应用服务器。
1.3.2 tomcat的下载和安装
安装:下载绿色版tomcat后,解压到本地磁盘即完成安装
1.3.3 tomcat结构目录
①bin:启动和关闭tomcat的bat文件。
- startup.bat , shutdown.bat 用于在windows下启动和停止脚本;
- startup.sh, shutdown.sh 用于在linux下启动和停止脚本;
②conf:配置文件。
- logging.properties Tomcat 的日志配置文件, 可以通过该文件修改Tomcat 的日志级别、日志字符编码及日志路径等
- server.xml该文件用于配置server相关的信息,比如tomcat启动的端口号,配置主机(Host)。
③lib:该目录放置运行tomcat运行需要的jar包。
④logs:存放日志,当我们需要查看日志的时候,可以查询信息。
⑤webapps:放置我们的web应用。
⑥work工作目录:该目录用于存放jsp被访问后生成对应的server文件和.class文件。
1.3.4 tomcat的启动和关闭
启动:双击 bin/startup.bat 文件 ;
停止:双击 bin/shutdown.bat 文件 ;
访问:http://localhost:8080
1.4 war包
war 包是 Sun 提出的一种 web 应用程序格式,它与 jar 类似是一个特殊的压缩包。
一个 war 文件包含 Servlet、HTML 页面、Java 类、图像文件及其他资源,简单的来说,jar 只是类的归档文件,而 war 包是一个完整的 web 应用程序。
我们war文件直接放在 Tomcat 的 webapps 文件夹下就可以启动该项目了。
2.Http协议
什么是Http协议: 浏览器和服务器之间进行数据传输需要遵循的格式规范。
2.1 请求行
主要包含:请求方式、请求URL、状态码、HTTP协议及版本
2.2 请求头
- Accept:表示浏览器能接收的资源类型,如text/*,image/或者/*表示所有。
- Accept-Encoding:告诉服务器当前浏览器支持的内容编码。
- Accept-Language:告诉服务器当前浏览器能接受和处理的语言。
- Connection:keep-alive,告诉服务器在完成本次请求的响应后,保持该TCP连接不释放,等待本次连接的后续请求。这样可以减少打开关闭TCP连接的次数提升处理性能。另外的可选项是Close,表明直接响应接受完成后直接将其关闭。
- Content-Length:用于描述HTTP消息实体的传输长度。
- Content-Type:内容类型,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。
- Cookie:表示服务器端为本次访问分配了一个Session ID,每次发送请求时都会主动将该Session ID通过Cookie字段又发送回服务器,用于验证身份和保持状态。
- Host:描述请求将被发送的目的地,在任何类型的请求中都会包含此信息。
- Origin:用来说明请求从哪里发起的。
- Referer:指定发起该请求的源地址。
- TE:采用何种传输编码。
- User-Agent:是一种向访问网站提供你所使用的浏览器类型及版本、操作系统及版本、浏览器内核等信息的标识。
- X-Requested-With:用来判断请求是Ajax请求还是其他请求。
2.3 请求体
POST
请求通过请求体来传递数据,通过param1=value1¶m2=value2的键值对形式编码。GET
请求通过URL地址参数来传递数据,也就是我们平时看到的URL地址里面“?”后面的所包含的键值对。
2.4 响应头
服务器响应的第一行总是版本号+空格+数字+空格+文本,数字表示响应代码,其中2xx表示成功,3xx表示重定向,4xx表示客户端引发的错误,5xx表示服务器端引发的错误。数字是给程序识别,文本则是给开发者调试使用的。常见的响应代码有:
-
响应代码:
200 OK
:表示成功;- 301 Moved Permanently:表示该URL已经永久重定向;
302 Found
:表示该URL需要临时重定向;304 Not Modified
:表示该资源没有修改,客户端可以使用本地缓存的版本;400 Bad Request
:表示客户端发送了一个错误的请求,例如参数无效;- 401 Unauthorized:表示客户端因为身份未验证而不允许访问该URL;
- 403 Forbidden:表示服务器因为权限问题拒绝了客户端的请求;
404 Not Found
:表示客户端请求了一个不存在的资源;- 405 :请求方式不对,eg:get请求方式去访问doPost()
500 Internal Server Error
:表示服务器处理时内部出错,例如因为无法连接数据库;503 Service Unavailable
:表示服务器此刻暂时无法处理请求。
-
content-encoding
:响应的编码格式 -
content-type
:响应内容的类型 -
date:响应的时间。此处使用的是GMT标准时间
-
server:处理请求的源头服务器所用到的软件相关信息
-
strict-transport-security:
HTTP Strict Transport Security(通常简称为HSTS)是一个安全功能,它告诉浏览器只能通过HTTPS访问当前资源, 禁止HTTP方式。
2.5 响应体
响应体就是服务器返回的HTML页面或者json数据
3.Servlet入门
3.1 Servlet介绍
3.1.1 什么是Servlet?
Servlet是Server Applet的简称,是用Java编写的是运行在 Web 服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
3.1.2 Servlet的使用方法
Servlet技术的核心是Servlet接口,定义了Servlet与Servlet容器之间的契约,Servlet容器将Servlet类载入内存,生成Servlet实例并调用它具体的方法,所以它是所有Servlet类必须直接或者间接实现的一个接口。
3.1.3 Servlet接口的继承结构
-
Servlet接口:只负责定义Servlet程序的访问规范;
-
GenericServlet抽象类:实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,并提供了一些ServletConfig的使用方法;
-
HttpServlet抽象类:实现了service方法,并实现了请求分发处理;
3.2 Servlet快速入门
3.2.1创建javaweb项目
3.2.1.1 创建maven工程
3.2.1.2 添加webapp目录
-
右击项目,选择Add Frameworks Support
-
选择Web Application,再点击OK
-
将web目录拖拽到main目录下,并改名为webapp
- webapp:静态资源比如 html css js jsp可以定义在web下面
- WEB-INF:里面的资源不能直接被外界访问 web.xml 是web项目的核心配置文件
- index.jsp:web项目的访问首页,在默认情况我们访问的首页就是index.jsp
3.2.2 添加依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
由于Servlet版本分为<=4.0和>=5.0两种,所以,要根据使用的Servlet版本选择正确的Tomcat版本。从Tomcat版本页可知:
- 使用Servlet<=4.0时,选择Tomcat 9.x或更低版本;
- 使用Servlet>=5.0时,选择Tomcat 10.x或更高版本。
3.2.3 创建servlet实例
package com.by.servlet;
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse servletResponse)
throws ServletException, IOException {
servletResponse.setContentType("text/html;charset=utf-8");
servletResponse.getWriter().write("<h1>hello<h1>");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
3.2.4 配置servlet
- web.xml中配置
<!--
配置Servlet
servlet-name:servlet的名称
servlet-class:servlet的全类名
url-pattern: 访问servlet的url
-->
<servlet>
<servlet-name>hello</servlet-name>
<!-- servlet-name要和servlet-mapping所对应,映射的关系-->
<servlet-class>com.by.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 注解方式配置
@WebServlet("/hello")
public class HelloServlet implements Servlet {}
3.2.5 设置打包方式
- 修改pom.xml
<!--打包方式-->
<packaging>war</packaging>
3.2.6 部署web项目
- 点击“Edit Configurations”
- 点击"+"
- 点击Tomcat Server中的Local
- 配置Tomcat路径
- 部署web项目
- 启动tomcat
- 查看是否部署成功
3.2.7 测试
浏览器访问:http://localhost:8080/01_servlet_HelloWorld_war/hello
3.3 servlet的生命周期
3.3.1 什么是servlet的生命周期
Servlet的生命周期就是servlet类对象什么时候创建?什么时候调用对应的方法,什么时候销毁。
对象的生命周期:
Student student = new Student(); //创建对象
student.setName("eric"); // 使用对象
student.show();// 使用对象
student = null; // 销毁对象
也就是说自定义对象的生命周期由我们程序员自己手动控制。但是!!!Servlet它不是一个普通的java类。是一个被tomcat服务器调用的。所以Servlet是生命周期是被tomcat服务器去控制的。
3.3.2 servlet生命周期中重要的方法
-
构造方法:创建servlet的时候调用。默认情况下,第一次访问servlet的时候,会创建servlet对象。此时会有且只会调用1次构造函数,证明了servlet对象是单实例的。
-
init方法:创建完servlet对象之后调用,也只是会调用1次。
-
service方法:提供服务的方法,接收用户的请求,并处理用户的请求,然后响应用户的请求。每次发送请求,都会调用service方法。调用几次,service方法会执行几次。
-
destroy方法:销毁的方法。销毁servlet对象的时候调用。比如我们停止tomcat服务器或者重新部署tomcat服务器,都会销毁servlet对象,只会调用1次。
3.3.3 tomcat服务器内部执行代码的原理
用户发送请求
tomcat服务器会根据用户发送的请求,解析web.xml配置文件,获取servlet-class的全限定名路径(com.by.servlet.ServletDemo)获取字节码对象,然后通过字节码对象获取对应的实例对象
Class clazz = Class.forName(“com.by.servlet.ServletDemo”);
Object o = clazz.newInstance();创建ServletConfig对象,然后调用init方法
Method method = clazz.getDeclaredMethod(“init”,ServletConfig.class);// 获取方法对象
method.invoke(o,config);创建request对象,创建response对象,然后调用service方法
Method m = clazz.getDeclaredMethod(“service”,ServletRequest.class,ServletResponse.class);
m.invoke(o,request,response);销毁servlet实例对象,也是通过反射的机制实现的
Method m1 = clazz.getDeclaredMethod(“destroy”,null);
m1.invoke(o,null);
3.3.4 测试servlet的声明周期
public class LifeCycleServlet implements Servlet {
public LifeCycleServlet(){
System.out.println("LifeCycleServlet has run........");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init method has run........");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service method has run........");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy method has run........");
}
}
4 创建servlet的三种方式
4.1 实现Servlet接口的方式
@WebServlet("/test1")
public class Servlet1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//s使用ServletConfig对象初始化我们的Servlet
//执行了,从这个地方可以说明一个问题 Servlet已经被实例化了
System.out.println("init方法执行");
}
@Override
public ServletConfig getServletConfig() {
//获取servlet配置信息对象
//没有执行
System.out.println("getServletConfig方法执行");
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//解决中文乱码问题
servletResponse.setContentType("text/html;charset=utf-8");
servletResponse.getWriter().append("我是Servlet接口创建的Servlet");
}
@Override
public String getServletInfo() {
//获取Servlet的详细信息
//没有执行
System.out.println("getServletInfo方法执行");
return null;
}
@Override
public void destroy() {
//当tomcat关闭的时候,执行销毁这个servlet的方法
System.out.println("destroy方法执行");
//只有当tomcat关闭的时候,才会执行这个方法
}
}
4.2 继承GenericServlet抽象类的方式
@WebServlet("/test2")
public class Servlet2 extends GenericServlet {
//只有一个方法是必须重写的,抽象方法
//为什么?service是核心方法,因为请求和响应就是执行这个方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//解决中文乱码问题
servletResponse.setContentType("text/html;charset=utf-8");
servletResponse.getWriter().append("我是GenericServlet抽象类创建的Servlet");
}
}
4.3 继承HttpServlet的方式
@WebServlet("/test3")
public class Servlet3 extends HttpServlet {
//因为在前端的时候,有两种请求方式get和post
//doGet和doPost方法写在了Service方法中了
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("我是HttpServlet创建的Servlet");
}
}
HttpServlet抽象类使用HttpServletRequest和HttpServletResponse继承并增强了ServletRequest和ServletResponse类
-
H t t p S e r v l e t R e q u e s t \boxed{HttpServletRequest} HttpServletRequest封装了一个HTTP请求,我们通过其实例req可以拿到HTTP请求的几乎全部信息,常用的方法有:
- getMethod():返回请求方法,例如,
GET
,POST
; - getRequestURI():返回请求路径,但不包括请求参数,例如,“/hello”;
- getQueryString():返回请求参数,例如,“name=Bob&a=1&b=2”;
getParameter(name)
:返回请求参数,GET请求从URL读取参数,POST请求从Body中读取参数;- getContentType():获取请求Body的类型,例如,“application/x-www-form-urlencoded”;
- getContextPath():获取当前Webapp挂载的路径,对于ROOT来说,总是返回空字符串"";
- getCookies():返回请求携带的所有Cookie;
- getHeader(name):获取指定的Header,对Header名称不区分大小写;
- getHeaderNames():返回所有Header名称;
- getInputStream():如果该请求带有HTTP Body,该方法将打开一个输入流用于读取Body;
- getReader():和getInputStream()类似,但打开的是Reader;
- getRemoteAddr():返回客户端的IP地址;
- getScheme():返回协议类型,例如,“http”,“https”;
- getMethod():返回请求方法,例如,
可通过request.setCharacterEncoding(“utf-8”);解决从前端获取的中文数据乱码的问题
此外,HttpServletRequest还有两个方法:setAttribute()
和getAttribute()
,可以给当前HttpServletRequest对象附加多个Key-Value,相当于把HttpServletRequest当作一个Map<String, Object>使用。
-
H
t
t
p
S
e
r
v
l
e
t
R
e
s
p
o
n
s
e
\boxed{HttpServletResponse}
HttpServletResponse封装了一个HTTP响应,提供了许多设置Header的方法,常用的设置Header的方法有:
- setStatus(sc):设置响应代码,默认是200;
- setContentType(type):设置Body的类型,例如,“text/html”;
- setCharacterEncoding(charset):设置字符编码,例如,“UTF-8”,可解决浏览器响应内容中文乱码的问题;
- setHeader(name, value):设置一个Header的值;
- addCookie(cookie):给响应添加一个Cookie;
- sendRedirect():重定向
这三个创建方式选择哪个?
最好的方式是继承HttpServlet
可以减少对其他方法的要求 init destroy
可以根据前端的要求进行分门别类 doGet doPost
5.重定向和转发
5.1 重定向
- 什么是重定向
重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令(302状态码),告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。
一个页面跳转到另外一个页面(应用场景)、登录页面跳转到主页面:
login.jsp====> LoginServlet====>main.jsp
-
特征:
- 重定向的过程是浏览器(客户端)的行为
- 实际上浏览器做了2次请求(当点击登录按钮的时候做了两次请求)(分别是请求login和main.jsp)
- 注意上一次请求的request对象会丢失
- 重定向有一个非常明显的特征,即浏览器的url变化了
-
RedirectServlet
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符编码
request.setCharacterEncoding("utf-8");
request.setAttribute("name", "二狗");
response.sendRedirect("main.jsp");
}
}
- 重定向核心代码
response.sendRedirect(“main.jsp”);
5.2 请求转发
- 什么是请求转发
请求转发是指内部转发。当一个Servlet处理请求的时候,它可以决定自己不继续处理,而是转发给另一个Servlet处理。
-
特征:
- 转发是服务器的行为
- 浏览器在这个过程中只有一次请求
- 可以传递带有数据的request
- url不会发生任何的变化
-
ForwardServlet
@WebServlet("/redirect")
public class ForwardServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符编码
request.setCharacterEncoding("utf-8");
request.setAttribute("name", "二狗");
request.getRequestDispatcher("main.jsp").forward(request, response);
}
}
- 请求转发核心代码
request.getRequestDispatcher(“main.jsp”).forward(request,response);
6.Servlet自动加载
- 为什么要用自动加载
默认情况下,第一次访问servlet的时候,创建servlet对象。如果servlet构造函数里面的代码或者init方法里面的代码比较多,就会导致用户第一次访问servlet的时候比较慢。
这个时候,我们可以改变servlet对象的创建时机:在启动服务器、加载web应用时创建servlet对象。在servlet的配置信息中,加上一个<load-on-startup>
标签即可。
- 如何设置自动加载
<servlet>
<servlet-name>forward</servlet-name>
<servlet-class>com.by.servlet.ForwardServlet</servlet-class>
<!--容器是否在启动时加载该servlet,数字越小优先级越高越高-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>forward</servlet-name>
<url-pattern>/forward</url-pattern>
</servlet-mapping>
这样配置之后,servlet的构造函数和init方法就会在web应用加载的时候就会执行。
7.ServletConfig对象
- 是什么
ServletConfig是javax.servlet.包下的一个接口,ServletConfig它是Servlet的一个配置对象;
ServletConfig是由tomcat容器创建,通过init方法传入给Servlet;
- ServletConfig对象如何获取?
ServletConfig servletConfig = getServletConfig();
HttpServlet抽象类继承了GenericServlet抽象类
因此在继承Httpservlet或GenericServlet实现的servlet中,可直接调用getServletConfig()
获取ServletConfig对象
- 常用方法
getInitParameter(String parameterName); //根据参数名称获取指定的参数值
getInitParameterNames(); //获取所有的参数名称
- 获取servlet里面定义的初始化参数
<servlet>
<servlet-name>servletConfig</servlet-name>
<servlet-class>com.by.servlet.ServletConfigServlet</servlet-class>
<!--Servlet的初始化参数-->
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>root123</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servletConfig</servlet-name>
<url-pattern>/servletConfig</url-pattern>
</servlet-mapping>
public class ServletConfigServlet extends HttpServlet {
@Override
public void service(ServletRequest servletRequest,
ServletResponse servletResponse) throws ServletException {
//1.获取ServletConfig对象
ServletConfig servletConfig = getServletConfig();
//2.获取Servlet中的初始化参数
String username = servletConfig.getInitParameter("username");
String password = servletConfig.getInitParameter("password");
//3.输出数据
System.out.println(username);
System.out.println(password);
}
}
8.ServletContext对象
- 是什么
ServletContext是javax.servlet包下的一个接口,又称上下文对象,是配置对象也是一个域对象;
当服务器启动时,会为服务器中的每一个web项目创建一个ServletContext对象;
在web应用中的servlet要想实现资源的共享,可以通过ServletContext来完成;
- 如何获取这个对象
ServletContext servletContext = getServletContext();
HttpServlet抽象类继承了GenericServlet抽象类
因此在继承Httpservlet或GenericServlet实现的servlet中,可直接调用getServletContext()
获取ServletConfig对象
- 这个对象里面也有很多方法:
getInitParameter() //获取指定参数名称的全局参数值
getRealPath(String path) //获得当前项目的服务器磁盘路径
getContextPath() //获取项目的根路径
getAttribute(String parameterName) //获取ServletContext域中指定名称的参数值;
setAttribute(String paramterName,Object parameterValue) //存储参数到ServletContext域中;
removeAttribute(String parameterNam) //将ServletContext域中指定名称的参数移除;
- 定义全局初始化参数
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>root456</param-value>
</context-param>
- 获取全局初始化参数
使用ServletContext对象可在该web项目中的任意servlet获取全局初始化参数
public class ServletContextServlet extends HttpServlet {
@Override
public void service(ServletRequest servletRequest,
ServletResponse servletResponse) throws ServletException {
//获取ServletContext对象
ServletContext servletContext = getServletContext();
//1.获取全局初始化参数
String username = servletContext.getInitParameter("username");
System.out.println(username);
String password = servletContext.getInitParameter("password");
System.out.println(password);
//2.获取服务器真实路径
String upload = servletContext.getRealPath("");
System.out.println(upload);
//3.获取项目的根路径
String contextPath = servletContext.getContextPath();
System.out.println(contextPath);
//4.往ServletContext域中,存储一个名称为msg的属性,值为"hello"
String str = "hello";
servletContext.setAttribute("msg",str);
}
}
8.Cookie和Seesion
8.1 Cookie
http协议是一个无状态的协议,你每一个跳转到下一个页面的时候都是需要先登录才能使用,这样就很麻烦比如淘宝,没有cookie和session的话,用户在首页已经登录上去了,但是需要再次登录才能选择商品,需要再次登录才能放到购物车,需要再次登录才能然后购买,这样用户的体验是相当差的。
- 什么是Cookie?
- cookie是在
浏览器中保存的
- 如果想要使用cookie要保证我们的
浏览器是开启cookie
,所以说有一定的弊端,如果浏览器没有开启cookie,就不能再使用cookie了- cookie的
大小是有限制的,通常是4096byte
- cookie的保存是以
键值对
的形式存在的
- 使用方法
- 添加Cookie
//新建一个Cookie,通过构造方法直接设置key和value
Cookie msg = new Cookie("msg", "Hello World");
//设置cookie最大存活时间
msg.setMaxAge(60*60*24);
//将cookie添加到网页上
resp.addCookie(msg);
- 修改Cookie
//从请求上获取Cookie数组
Cookie[] cookies = req.getCookies();
//遍历数组,找到要修改的cookie
for (Cookie cookie : cookies) {
if (cookie.getName().equals("JSESSIONID")){
//修改cookie的value值
cookie.setValue("are_you_ok");
//重新添加,覆盖原来的cookie使修改生效
resp.addCookie(cookie);
}
}
- 删除Cookie
//从请求上获取Cookie数组
Cookie[] cookies = req.getCookies();
//遍历数组,找到要删除的cookie
for (Cookie cookie : cookies) {
if (cookie.getName().equals("msg")){
//将存活时间设为0即为删除
cookie.setMaxAge(0);
//重新添加,覆盖原Cookie
resp.addCookie(cookie);
}
}
8.2 Session
- 什么是Session
保存服务器中
- 当用户发送一个HTTP请求到服务器时,服务器会检查该请求是否包含session标识符(通常是存cookie),如果没有,则会创建一个新的session(存储区域),并将session标识符发送给客户端。浏览器再发送请求时会携带session标识符,此时服务器根据session标识符就可以找到对应的session(存储区域)
使用session的时候一般要开启cookie如果浏览器没有开启cookie功能,我们可以通过html的url传参完后session的使用
没有大小的限制
- 信息的保存也是以
键值对
的形式存在的
- 使用方法
- 添加Session
//获取Session对象
HttpSession session = req.getSession();
//设置参数
session.setAttribute("msg","nb");
//设置最大未访问时长,超过则session失效
session.setMaxInactiveInterval(60*60*24);
- 获取Session
//获取Session对象
HttpSession session = req.getSession();
//获取参数
Object msg = session.getAttribute("msg");
//输出sessionId和msg参数
System.out.println(session.getId());
System.out.println("msg="+msg);
- 删除Session
//获取session对象
HttpSession session = req.getSession();
//删除参数
session.removeAttribute("msg");
//将session设为失效,再次发请求时服务器会再创建一个session,使用新的sessionID
session.invalidate();
8.3 四大作用域
四大作用域,也可以说是四种域对象
的生效范围,从大到小分别是:
标识符 | 作用域 | 存活时间 |
---|---|---|
ServletContext | tomcat | 服务器运行期间 |
Session | 浏览器 | 浏览器运行期间 |
Servlet | 一次请求 | 请求存活期间 |
PageContext | 页面 | 页面显示期间 |
9.过滤器和监听器
9.1 过滤器
- 什么是过滤器
当浏览器向服务器发送请求的时候,过滤器可以将请求拦截下来,完成一些特殊的功能,比如:编码设置、权限校验、日志记录等。
- 为什么要使用过滤器
从前台获取中文数据时如果不设置编码格式,则获取到的数据会乱码,为了解决乱码,每次编写新的servlet都需要设置一下编码格式,过于繁琐。
有没有什么方法可以只配置编码格式一次后,在所有的servlet都生效呢?
这时候filter就出来了,配置filter后可以将所有请求在执行对应的servlet之前,先过一遍filter,
如果在filter里边设置编码的话,那么经过filter的所有servlet就不用单独设置了。
- Filter实例
public class CharEncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
//请求进入,经过过滤器
System.out.println("请求进入,经过过滤器");
//设置编码格式
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//请求放行,调用servlet
filterChain.doFilter(req,resp);
//请求返回,经过过滤器
System.out.println("请求返回,经过过滤器");
}
@Override
public void destroy() {
}
}
- 使用过滤器需要注意的事项:
- 过滤器
必须实现Filter接口
。 - 过滤器拦截的请求执行完毕之后,
必须要放行
,否则我们的请求就不会被执行。
filterChain.doFilter(request,response); //过滤器放行
- 我们可以使用@WebFilter来配置过滤器要拦截的资源,当然我们也可以通过xml的方式配置过滤器。
<filter>
<filter-name>filter</filter-name>
<filter-class>com.by.servlet.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- Filter的拦截路径的配置
- 拦截具体的资源路径:/index.jsp,只有访问index.jsp的时候才会被拦截
- 目录拦截:/user/*,访问/user下的所有资源,都会被拦截
- 后缀名拦截:*.do 访问后缀名为do的资源,都会被拦截
- 拦截所有:/* 访问所有的资源,都会被拦截
9.2 监听器
- 什么是监听器
\监听器可以监听ServletContext,session,request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。
监听器分类 | 监听器名称 | 作用 |
---|---|---|
Servletcontext监听 | ServletContextListener | 用于对Servletcontext对象进行监听(创建、销毁) |
ServletContextAttributeListener | 对Servletcontext对象中属性的监听(增删改属性) | |
Session监听 | HttpSessionListener | 对session对象的整体状态的监听(创建、销毁) |
HttpSessionAttributeListener | 对session对象中的属性监听(增删改属性) | |
HttpSessionBindingListener | 监听对象于Session的绑定和解除 | |
HttpSessionActivationListener | 对session数据的钝化和活化的监听 | |
Request监听 | ServletRequestListener | 对Request对象进行监听(创建、销毁) |
ServletRequestAttributeListener | 对Request对象中属性的监听(增删改属性) |
- 使用方法
- 创建监听器
public class MyListener implements ServletContextListener, HttpSessionListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("tomcat启动,创建ServletContext对象");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("tomcat关闭,销毁ServletContext对象");
}
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("浏览器第一次访问tomcat,创建session");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session失效,销毁session");
}
}
- 配置监听器
<listener>
<listener-class>com.by.Listener.MyListener</listener-class>
</listener>
10.web三层架构
我们的开发架构一般都是基于两种形式,一种是 C/S 架构
,也就是客户端/服务器,另一种是 B/S 架构
,也就是浏览器服务器。在 JavaEE 开发中,几乎全都是基于 B/S 架构的开发。
那么在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。
三层架构中,每一层各司其职,接下来我们就说说每层都负责哪些方面:
- 表现层(web/servlet):
也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层,web 需要接收 http 请求,完成 http 响应。
表现层包括展示层
和控制层
:控制层负责接收请求,展示层负责结果的展示。
表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。
表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系)
MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,
是一种用于设计创建 Web 应用程序表现层的模式。MVC 中每个部分各司其职:
- Model(模型):
通常指的就是我们的数据模型。作用一般情况下用于封装数据。
- View(视图):
通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。
通常视图是依据模型数据创建的。
- Controller(控制器):
是应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。
- 业务层(service):
也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。
业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也就是我们说的,事务应该放到业务层来控制)
- 持久层(dao):
也就是我们是常说的 dao 层
。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。通俗地讲,持久层就是和数据库交互,对数据库表进行增删改查的
。