浏览器请求处理流程:浏览器发请求 => 服务器tomcat( => 应用程序 ( => servlet) )
Servlet应用的三大作用域:request,session,application
tomcat存放项目的层级结构
注释:servlet原引用包名 javax.servlet,2017年,被oracle把servlet捐给了eclipse基金会,不让使用java包名,tomcat10之后,servlet的包名更名为jakarta.servlet。
配置的加载顺序: ServletContext> context-param > listener > filter > servlet
web-app 根标签:xmlns:xsi 命名空间实例,xmlns xml文档位置,xsi:schemaLocation 模式位置
应用名称:display-name // 不影响程序执行,可省略不写(非必须)
应用描述:description // 不影响程序执行,可省略不写(非必须)
(1) 上下文参数:context-param // 可以配置多个或不写,用于程序启动时获取全局变量。
(2) 参数名:context-name
(3) 参数值:context-value // 值也可以是配置文件,默认在WEB-INFO下读取,配置到其他路径
(1) 监听器:listener // 监听全局,会话,请求,的创建销毁与域对象的变更
(2) 监听处理类:listener-class
(1) 过滤器:filter
(2) 过滤器名:filter-name
(3) 过滤器类:filter-class
(4) 过滤器参数:init-param, param-name, param-value
(5) 过滤器配置:filter-mapping
(6) 过滤器过滤路径:url-pattern // 匹配的是url名称与资源是否存在无关。
(7) 过滤拦截器名:servlet-name // web.xml只能拦截web.xml配置的servlet名,注解servlet拦不住
(8) 过滤器访问权限:dispatcher
注释:dispatcher配置:REQUEST(过滤器应用于来自客户端的请求), INCLUDE(应用于RequestDispatcher的include请求), FORWARD(应用于RequestDispatcher的forward请求), ERROR(应用于发生错误引起的转发请求)
(1) 处理器:servlet
(2) 处理器名:servlet-name
(3) 处理器类:servlet-class
(4) 处理器参数:init-param, param-name, param-value
(5) 处理器加载顺:load-on-startup // 不写或负数首次访问加载,0-10由小到大加载
(6) 处理器配置:servlet-mapping
(7) 处理器处理路径:url-pattern
(1) 会话配置:session-config
(2) 会话超时时间:session-timeout // 单位分钟,负数或0永久有效。
注释:应用web.xml不设置默认执行的是tomcat的配置30分钟会话超时。
(1) 配置MIME:mime-mapping
(2) 文件后缀:extension
(3) 传送方式:mime-type
注释:当浏览器访问服务器的文件时,根据文件后缀匹配extension找到mime-type,以该方式将文件传输给浏览器。text/plain和text/html是浏览器可识别直接能打开的类型。浏览器不识别的类型会下载该文件。tomcat默认配置了大部分类型的文件,应用内配置mime主要用于自定义文件后缀的识别。***注意修改mime-mapping配置后需要清空浏览器缓存才会生效。
(1) 欢迎页列表:welcome-file-list // 默认欢迎页,不指定servlet请求的默认显示页面
(2) 欢迎页: welcome-file // 配置默认显示页面,按定义的先后顺序,执行优先级表示
注释:不配置默认找 webapp根目录下的 index.html 没有则找 index.jsp,还没有报404错误
(1) 异常配置:error-page
(2) 错误码:error-code // 404,配置错误码,拦截错误或response.sendError返回的错误码
(3) 异常类:exception-type // 异常类配置
(4) 异常处理页面:location // 值 /xxx.jsp,/servlet 要跳转的页面或请求
注释:jsp配置的是单个页面的错误页,优先级高。web.xml配置的是整个应用的错误页。
java.lang.Throwable是异常的根类,location必须以/开头,代表应用根目录
<jsp-config>
<taglib> 标签库
</taglib>
<jsp-property-group>
<description> 设置说明 </description>
<display-name> 设定名称</display-name>
<url-pattern>/WEB-INF/jsp/xx.jsp</url-pattern> // 影响范围 例如:*.jsp
<el-ignored>true</el-ignored> // true 不支持el , false 支持el
<scripting-invalid>false</scripting-invalid> // true 不支持jsp声明,脚本,表达式
<page-encoding>UTF-8</page-encoding> // jsp网页编码 例如:GBK
<include-prelude>/WEB-INF/jsp/common/xx.jspf<include-prelude> // jsp网页头引用,.jspf
<include-coda>/WEB-INF/jsp/common/xx.jspf<include-coda> // jsp网页结尾,.jspf
</jsp-property-group>
</jsp-config>
Web容器(tomcat)启动时为每个web应用创建唯一的ServletContext实例
(1) request.getServletContext() // Servlet,GenericServlet,HttpServlet,JSP
(2) request.getSession().getServletContext() // HttpServlet,JSP
(3) getServletConfig().getServletContext() // Servlet,GenericServlet,HttpServlet,JSP
(4) getServletContext() // GenericServlet,HttpServlet,JSP
(1) 获取参数value值:servletContext.getInitParameter("param1");
(2) 获取全部name值:servletContext.getInitParameterNames();
(1) 获取全局域对象值:servletContext.getAttribute("key")
(2) 设置全局域对象值:servletContext.setAttribute("key","value")
(3) 删除全局域对象值:servletContext.removeAttribute("key");
(4) 获取全局域对象名:servletContext.getAttributeNames();
全局转发:context.getRequestDispatcher("/WEB-INF/JSP/xx.jsp").forward(request, response); // 省略了/应用名,只能转本应用下 /开头的应用根目录请求,不能跨应用。与请求转发不同必须以/开头。
(1) 新建配置对象:Properties pro = new Properties();
(2) 取得ServletContext:ServletContext context = getServletContext();
(3) 取得文件流:InputStream in = context.getResourceAsStream("/WEB-INF/test.properties");
(4) 加载配置文件数据:pro.load(in);
(5) 关闭文件流:in.close();
(6) 取得配置文件内容:String name = (String)pro.getProperty("username");
(1) 获取应用请求路径:servletContext.getContextPath(); // 获取【/应用的请求】
(2) 获取配置的项目名:servletContext.getServletContextName(); // 获取应用名
(3) 获取服务器名:servletContext.getServerInfo(); // 获取 Apache Tomcat/版本号
(4) 获取项目盘符:servletContext.getRealPath("/"); // 获取 盘符:\路径...\应用名\
(5) 略
一共有8个监听器接口,随着技术变化只有ServletContextListener有用。
(1) 监听全局对象的创建与销毁:ServletContextListener // 服务器启动时创建,停止时销毁
(2) 监听全局的域对象:ServletContextAttributeListener // 添加修改删除全局域时触发
(1) 监听请求的创建与销毁:ServletRequestListener // 请求开始创建,请求结束销毁
(2) 监听请求的域对象:ServletRequestAttributeListener // 添加修改删除请求域时触发
(1) 监听会话的创建与销毁:HttpSessionListener // 首次请求后创建,超时或退出销毁
(2) 监听会话的域对象:HttpSessionAttributeListener // 添加修改删除会话域时触发
(3) HttpSessionActivationListener
(4) HttpSessionBindingListener
(1) 注解配置:@WebListener
在后端处理请求之前拦截请求,在响应返回浏览器之前处理响应
创建filter步骤:(1)实现filter接口,(2)重写dofilter方法,(3)配置xml文件
需重写doFilter方法
(1) 实现init方法:init // 项目启动加载方法初始化只调用1次,可获取filterConfig
(2) 实现doFilter方法:doFilter // (req, res, chain) 执行过滤chain.doFilter转下一个过滤器处理
(3) 实现destroy方法:destroy // 项目停止时,执行。
GenericFilter实现了Filter接口,需重写doFilter方法
(1) 初始化:init
(2) 获取Filter名:getFilterName() // web.xml配置的filter-name
(3) 获取全局对象:getServletContext()
(4) 获取Filter对象:getFilterConfig()
(5) 获取Filter参数名:filterConfig.getInitParameterNames()
(6) 获取Filter参数值:filterConfig.getInitParameter("name")
HttpFilter继承了GenericFilter,需重写doFilter方法
(1) 执行过滤器:doFilter // 过滤器处理完,要继续执行需要调用FilterChain的doFilter方法,不调用则不会执行后续filter或servlet,若过滤器拦截请求用return结束程序。
(1) 第一优先级:url-pattern // 【/*】【*.do】由配置顺序从上到下先执行
(2) 第二优先级:servlet-name // 【web.xml配置的servlet-name】
执行优先级:urlPatterns或value【/*】【*.do】先执行,servlet-name后执行,
注释:同级的多个urlPatterns的过滤器,可能是按文件名的先后顺序执行的。
(1) URL配置:@WebFilter(urlPatterns="/xxx") // 等同于web.xml的
(2) 默认属性:@WebFilter(value="/xxx") // value与urlPatterns 作用相同
(3) 省略属性:@WebFilter("/xxx") // 只有value一个属性时可以省略属性名
(1) 多路径拦截:@WebFilter({"/xxx/*", "*.do"}) // 可指定拦截多种路径访问
(2) 精确拦截:@WebFilter("/xxx/xx") // 多层目录精确匹配
(3) 目录拦截:@WebFilter("/xxx/*") // 结尾/*任意匹配
(4) 扩展名匹配:@WebFilter("*.do") // 【任意.do】访问,前不加斜线
(1) filterName:等同于配置文件
(2) value:value与urlPatterns等同于配置文件
(3) initParams:等同与配置文件
(4) servletNames:// 指定过滤的servlet名,取web.xml或@WebServlet配置的servlet名
(5) dispatcherTypes:等同于配置文件
注释:@WebInitParam只能同 Webservlet 和WebFilter一起使用,只有name和value属性
处理请求之前,统一设定字符集
设置允许访问的资源
判断用户是否登录,及登录用户访问权限
创建servlet步骤:(1)继承Servlet接口,(2)重写抽象方法,(3)web.xml配置Servlet
(1) init:请求后判断没有servlet对象,则实例化一个对象,进行初始化init,只执行一次。
(2) getServletConfig:用于获取servlet配置对象
(3) getServletInfo:用于获取servlet的参数信息
(4) service:浏览器发请求后(多次请求多次调用),创建req,res对象,开新线程,调用service
(5) destroy:容器(tomcat)正常关闭时销毁处理,调用destroy
注释:获取ServletConfig的方式,1.init参数获取,2.Servlet子类中getServletConfig()获取
(1) 实现service方法:service // 处理请求,及响应
(1) 实现doGet方法:doGet // 处理get请求
(2) 实现doPost方法:doPost // 处理post请求
注释:doPut处理put请求,doDelete处理delete请求,doHead:读web头,doOptions:查特点选项,doTrace:返回收到的请求
Servlet3.0新增注解方式,无需配置servlet的web.xml文件,可不创建web.xml
(1) URL配置:@WebServlet(urlPatterns="/xxx") // 等同于web.xml的
(2) 默认属性:@WebServlet(value="/xxx") // value与urlPatterns 作用相同
(3) 省略属性:@WebServlet("/xxx") // 只有value一个属性时可以省略属性名
(1) 多路径请求:@WebServlet({"/xxx", "/xxx"}) // 可指定多种路径访问
(2) 精确匹配:@WebServlet("/xxx/xx") // 多层目录精确匹配
(3) 目录匹配:@WebServlet("/xxx/*") // 结尾/*任意匹配
(4) 扩展名匹配:@WebServlet("*.do") // 【任意.do】访问,前不加斜线
注释:url=主机(www.xx.com) +程序名(/webxx) + 处理器名(/xxservlet])+方法(/xx.do])+参数(?xx=xx)。uri=程序+servlet+方法。
(1) name:等同于配置文件
(2) value:value与urlPatterns等同于配置文件
(3) initParams:等同与配置文件
(4) loadOnStartup:等同于配置文件
注释:@WebInitParam只能同 Webservlet 和WebFilter一起使用,只有name和value属性
(1) 实例和初始化:init
(2) 就绪:service
(3) 销毁:destroy
(1) url回车 get方式
(2) 超链接 get方式
(3) 表单提交(submit, js, ajax) get, post 等
(1) 表单按钮提交:<input type="submit"> // 提交表单到form的action, 页面会刷新
(2) 按钮提交: // form内的按钮默认是提交按钮
(3) JS事件提交:
(4) 修改form默认提交事件:页面加载后 document.getElementById("formid").onSubmit = function () { ... this.submit(); }
(5) ajax提交:
(1) GET:参数在url中, 发送文本有限制225字符以内, 不安全数据url可见(url可缓存)
(2) POST:参数在请求体中,发文本或二进制长度没限制,相对安全url不可见(无缓存)
(3) PUT(4) DELETE(5) HEAD(6) OPTIONS(7) TRACE
注释:connect保留
(1) 请求行:请求方式 请求uri 请求协议/版本(get /xxx.html http/1.1)
(2) 请求头(键:值):
(3) 请求空行
(4) 请求体:get没有请求体。post请求, 封装内容(name=value&name=value)格式
user-Agent: // 浏览器及版本信息
accept: text/html //浏览器接收的MIME类型(text/heml, application/xhtml+html, */*)
accept-language:zh-CN //浏览器首选语言, 支持的语言环境
accept-encoding: // 客户端处理编码类型(gzip, )
Referer: http:localhost/xx.html // 告诉服务器请求来源,防止盗取链接,可统计来源信息
Connection: // 连接信息,是否链接状态
host:localhost:8080 // 服务器主机名和端口号
cookie: 会话信息
content-type:表单编码类型(text/plain, multipart/form-data(上传文件), application/x-www-form-urlencoded(默认格式))
服务器封装请求的数据,作成request,response对象,传给service方法处理。
(1) 获取客户端主机名:servletRequest.getRemoteHost()
(2) 获取客户端IP:servletRequest.getRemoteAddr()
(3) 获取客户端端口号:servletRequest.getRemotePort()
(4) 获取URL:httpServletRequest.getRequestURL()
(5) 获取URI:httpServletRequest.getRequestURI()
(6) 获取Servlet请求路径:httpServletRequest.getServletPath()
(7) 获取请求方式:httpServletRequest.getMethod()
过滤普通权限访问管理路径
(1) request.getHeader("key")
一般用不上这种方式
(1) 获取字符输入流:BufferedReader r = request.getReader() // 只能操作字符数据
(2) 获取内容:String line = null; while( (line=r.readLine() ) != null ) { ... } //line是&连接的参数,username=%E6%9D%8E%E5%9B%9B1&pwd=123&qx=0&ah=2&ah=3&zy=3
注释:此解析不出中文
(1) 获取表单参数值:getParameter("name") // text,password,hidden,radio,select,textarea
(2) 获取表单复数参数值:getParameterValues("name") // checkbox, select(multiple可多选)
(3) 取表单的所有请求名:getParameterNames()
(3) 取表单的所有键值对:getParameterMap()
(1) 获取请求域的值:request.getAttribute("key")
(2) 设置请求域的值:request.setAttribute("key", value)
(3) 删除请求域的值:request.removeAttribute("key")
(4) 获取请求域的名称:request.getAttributeNames()
(1) 请求转发:req.getRequestDispatcher("/WEB-INF/JSP/xx.jsp").forward(request, response);
注释:不能跨应用转发,只能访问当前应用内部项目资源,一次请求服务器内部转发,Url显示地址不变,/开头表示应用根目录,不以/开头表示servlet或jsp同级目录。
(1) 获取请求编码:request.getCharacterEncoding()
(2) tomcat7及以下(get,post)通用解决方案:
String reqstr = request.getParameter("name").getBytes("iso8859-1");
String str = new String(reqstr, "utf-8");
(3) tomcat8解决方案:
get解决对策:tomcat8默认解决了get的乱码问题
post解决对策: request.setCharacterEncodeing("UTF-8")
基于tcp/ip 端口80 一次请求一次响应,http无状态,请求之间独立。
版本 , 一次url访问图片,会产生多层请求,
版本1.0 每次请求建立新链接
版本1.1 复用链接
第一次握手:SYN=1, seq=x(随机) //本地端口(50515) => 访问服务器端口(80)
第二次握手:SYN=1, ACK=1 (1有效,0无效), ack=x+1, seq=y(随机) // 服务器80=>本地50515
第三次握手:ACK=1, ack=y+1, seq=x+1 // 本地50515=>服务器80
注释:本地=>服务器(我要访问你, 我是x标识, 我可能有其他连接x1,x2,), 服务器=>本地(可以访问, 我将你的x访问标记为y, 要建立连接么), 本地=>服务器(我是x, 你通过y标识同意了我的请求,让我们建立连接)
第一次挥手:FIN=1, seq=U // 本地端口50515 => 服务器端口80
第二次挥手:ACK=1, ack=U+1, seq=V // 80 => 50515
第三次挥手:FIN=1, ack=U+1, ACK=1, seq=W // 80 => 50515
第四次挥手:ACK=1, ack=W+1, seq=U+1 // 50515 => 80
注释:本地=>服务器(我要断开连接, 我是U), 服务器=>本地(我知道了, U你这次请求我标记为V, 等我会, 看看数据都给你传完没),服务器=>本地(U, 你的数据传完了,你可以通过W来断开连接,若没收到第4步回复再次这个发送),本地=>服务器(我是U, 你标记为W的请求可以断开了)
服务器发送探测报文,一般默认2小时,在应用层做心跳机制
(1) 状态行:请求协议/版本 状态码 响应状态(HTTP/1.1 200 OK)
(2) 响应头(键:值):Date: sat 01 Aug 2023/10/25 23:52:59 GMT...Content-Type: text/html
(3) 响应空行
(4) 响应HTML:...
(1) 响应类型:Content-Type // 设置服务器传送给浏览器数据的类型(MIME是因特网标准,用于识别文本,图片,声音,视频,程序专用数据等)
(2) 后端设置响应类型:res.setContenType("text/html; charset=UTF-8");
(3) 设置下载文件名:res.setHeader("Content-Disposition", "attachment;filename="+file.getName()); // 当响应类型为下载文件时需要设置文件名
word文档(application/msword)AcrobatPDF(application/pdf)Excel(application/vnd.ms-excel)ZIP文件(application/zip)gif图片(image/gif)jpeg图片(image/jpeg)html文档(text/html)文本(text/plain)mpeg视频(video/mpeg)midi音频(audio/midi)
字符流:res.getWriter().write("xxx"); // 返回html或字符数据
字符流:res.getWriter().print(97); // 返回html或字符数据,浏览器识别 ASCII为97的字符,显示a
字节流:res.getOutputStream().write("...".getBytes());// html或文本或二进制文件
字节流:res.getOutputStream().print(FileInputStream.read()...);// html或文本或二进制文件
方案1:
(1) 设置服务器编码:servletRes.setCharacterEncodeing("utf-8);
(2) 设置客户端编码:httpRes.setHeader("content-type", "text/html;charset=utf-8")
方案2:
(1) 同时设置服务器和客户端编码:servletRes.setContentType("text/html;charset=utf-8")
res.sendRedirect("Servlet20.do"); // 不以/开头为本应用目录,直接访问servlet
res.sendRedirect("/应用名/servlet"); // 以/开头为tomcat服务器目录,需指定应用名
res.sendRedirect("http://localhost:8080/应用名/servlet请求"); // 可重定向到其他网站
注释:重定向不能在响应out.flush(提交)之后进行,重定向不能请求WEB-INF下资源
res.sendError(异常状态码) // 返回一个异常code, 可通过web.xml拦截该异常
http请求是无状态的,跟踪客户端状态有4种方式
1.session, 2 cookie 3 url重写, 4隐藏表单域
(1) 获取session:HttpSession session = htttReq.getSession(); // 存在获取,不存在创建
(2) 获取session:httpReq.getSession(boolean); // true无对象则创建,false无对象返回null
(2) 获取Session标识:String id =session.getId(); // JSESSIONID服务器存在浏览器的sessionid,浏览器访问不传或者服务器没有这个id则服务器新建sessionid传给浏览器保存。
(1) 获取会话域的值:session.getAttribute("key")
(2) 设置会话域的值:session.setAttribute("key", value)
(3) 删除会话域的值:session.removeAttribut("key")
(4) 获取会话域所有名称:session.getAttrabuteNames()
(1) session.setMaxInactiveInterval(秒数); //负数和0当前会话永久有效,web.xml对所有会话有效
(2) 程序的web.xml文件
(3) tomcat 的conf目录下 web.xml文件
注释:1.httpsession.set方法设置优先级最高,2 web.xml配置优先级第二,3tomcat conf 的web.xml配置最低
(1) 长时间不操作页面则会话失效。// 根据配置的时间(默认30分钟)操作后重新计时。
(2) 关闭浏览器 // 关闭浏览器会清除JSESSIONID, 下次请求就不会传id, 相当于session失效。
(3) 立即销毁:session.invalidate();
注释:JSESSIONID存在cookie里,服务器返回 响应头 set-Cookie: JSESSIONID = 123AB24C... (32位16进制)。客户端访问时,发送请求头 Cookie: JSESSIONID = 123AB24C...
Cookie 是存储在客户端计算机上的文本信息。(包:javax.servlet.http.Cookie )
(1) 服务器脚本向浏览器发送一组Cookie信息,浏览器将信息存在本地。
(2) 浏览器向服务器发送请求时,把本地Cookie信息一起发送给服务器,用来让服务器识别用户。
(1) 新建cookie对象:Cookie cookie = new Cookie("key", "value");
(2) 获取cookie名:cookie.getName(); // cookie名不可变更
(3) 获取cookie值:cookie.getValue(name);
(4) 设置cookie值:cookie.setValue("值");
(5) 向客服端发送:response.addCookie(cookie);
(6) 获取cookie:Cookie[] cookies = request.getCookies(); // cookie只能从请求中获取,无法单独获取某一个cookie,只能全部获取if ( cookies != null && cookies.length > 0) { for (Cookie cookie : cookies) {...
(1) 关闭cookie失效:cookie.setMaxAge(-1) // 默认-1 关闭浏览器cookie失效
(2) 设置cookie失效时间:cookie.setMaxAge(正数) // 单位秒,超时浏览器自动删除该cookie
(3) 删除cookie: cookie.setMaxAge(0) // 0代表删除cookie
(1) 中文存储:tomcat7的cookie不能存中文。tomcat8的cookie可以存中文,不能存空格等特殊符号。
(2) 中文及特殊符号存储:URLEncoder.encode("这是 中文",Charset.forName("UTF-8"))
(3) 中文及特殊符号获取:URLDecoder.decode(cookie.getValue(),"UTF-8")
(1) 服务器cookie:cookie.setPath("/") // 当前服务器任意项目可获取
(2) 应用cookie:cookie.setPath("/项目名") // 只有当前项目可获取,默认设定。
(3) 请求cookie:cookie.setPath("/项目名/路径") // 只有指定的请求或路径可获取
(1) http传送:cookie.setHttpOnly(true) // http传送
(2) 加密传送:cookie.setSecure(true) // https传送