应用服务器和WEB服务器的区别:
|--应用服务器实现了JavaEE的所有规范,WEB服务器只实现了JavaEE中servlet和jsp这两个核心规范
|--常见的应用服务器有JBOSS、WebLogic、WebSphere
|--常见的WEB服务器有Tomcat、jetty
javaWeb的原理简单概述:
|--首先浏览器获取用户输入的URL地址并传输给tomcat服务器
|--接着tomcat服务器会根据传输过来的URL地址查找配置文件,判断该路径对应的是哪一个servlet程序
|--得到对应的servlet程序类名后通过反射机制得到该类并进行实例化
|--由于所有servlet程序类都实现了Servlet接口规范,故可以将得到的实例强转为Servlet类型
|--注意javeEE9之后,Servlet的包名由javax.servlet变更为jakarta.servlet
|--通过强转后的实例对象调用具体的方法实现功能即可
|--因此总的来说我们要做的就两点
|--servlet程序的开发
|--URL与servlet程序之间对应关系的配置(又称为servlet的注册)
servlet规范中对目录结构的要求:
|--webapps
|--web根目录
|--WEB-INF
|--classes文件夹
|--lib文件夹
|--web.xml(用于注册servlet)
|--html资源
|--css资源
|--javascript资源
|--imag资源
|--其他各种资源
配置tomcat服务器:
|--在环境变量中配置java环境变量
|--即配置JAVA_HOME和path
|--在环境变量中配置tomcat环境变量
|--即配置CATALINA_HOME和path
|--注意如果直接使用idea配置Tomcat服务器的话可以不用配置tomcat环境变量
|--通过startup.bat可以启动tomcat服务器,启动后访问本机8080端口会出现tomcat欢迎页
|--通过shutdown.bat可以关闭tomcat服务器
|--可以简单将tamcat理解为一个用java写的程序
|--解决tomcat服务器启动时日志输出乱码问题
|--将tomcat文件目录下的conf文件夹内的logging配置文件中的日志编码类型改成自己编译器对应的类型即可
web.xml配置文件格式:
|-------<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<!--每对servlet和servlet-mapping标签完成一组映射关系-->
<servlet>
<servlet-name>servlet程序类别名</servlet-name>
<servlet-class>servlet程序类全限定类名</servlet-class>
<!--让服务器一启动的时候就实例化servlet对象,并通过整数数值设置servlet实例化的顺序-->
<load-on-startup>整数数值</load-on-startup>
<!--用于配置servlet的初始化数据-->
<init-param>
<param-name>初始化数据名</param-name>
<param-value>初始化数据值</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servlet程序类别名</servlet-name>
<!--注意此处的URL是tomcat自动剪切掉协议名、域名、端口号、项目名路径之后的URL-->
<url-pattern>该servlet程序类所捆绑的URL</url-pattern>
</servlet-mapping>
<!--用于配置上下文的初始化数据-->
<context-param>
<param-name>初始化数据名</param-name>
<param-value>初始化数据值</param-value>
</context-param>
<!--用于配置URL中不指定资源文件路径时的展示路径(注意会默认从web根路径下开始查找)-->
<welcome-file-list>
<!--注意欢迎页设置中越往上优先级越高-->
<welcome-file>欢迎页文件路径</welcome-file>
</welcome-file-list>
<!--设置session超时时间,默认为30分钟-->
<session-config>
<session-timeout>XXX<session-timeout>
</session-config>
<!--每对filter和filter-mapping标签完成一组映射关系-->
<filter>
<filter-name>filter程序类别名</filter-name>
<filter-class>filter程序类全限定类名</filter-class>
</filter>
<filter-mapping>
<filtert-name>filter程序类别名</filter-name>
<!--注意此处的URL是tomcat自动剪切掉协议名、域名、端口号、项目名路径之后的URL-->
<url-pattern>该filter程序类所捆绑的URL</url-pattern>
</filter-mapping>
<!--配置需要用到的监听器类-->
<listener>
<listener-class>listener程序类全限定类名</listener-class>
</listener>
</web-app>
idea中配置javaWeb项目流程:
|--首先创建一个普通的javaSE项目工程或模块工程
|--接着为该工程添加web框架依赖
|--右键选择添加框架支持 --> 选择web支持 --> 勾选生成web.xml选项
|--将编译阶段需要用到的jar包导入并添加入库
|--例如servlet-api.jar等
|--编写需要的Servlet程序类
|--在类中继承并实现Servlet接口中的方法
|--一般来说业务功能都在service方法中实现
|--编写web.xml文件中的配置规则
|--将项目部署到tomcat服务器上
|--点击Add Configuration --> 选择tomcat中的local模板
|--一般来说我们需要配置的就是服务器的名称、服务器源路径、JRE环境依赖
|--在Deployment部署选项卡中添加需要部署的项目
|--在部署选项卡页面我们还需设置该项目名的项目名路径(即Application contxt)
|--服务器会自动将该名字替换为web根路径文件夹的名字
|--注意如果有项目运行时需要用到的但tomcat中没有的jar包需要fix到服务器中
|--或者直接将该jar包拷贝一份至该项目依赖的tomcat的lib文件夹中
|--或者直接拷贝一份到WEB-INF目录下的lib文件夹中
servlet生命周期:
|--servlet对象在被用户请求时被创建
|--servlet对象被创建后立即调用一次init方法、service方法
|--init方法用于完成初始化的相关操作
|--service方法用于执行各项具体的功能代码
|--接着在servlet对象被销毁之前的每一次请求都只执行service方法,不再创建对象
|--所以我们也常把servlet称为假单例模式
|--服务器被关闭时执行destroy方法,用于销毁servlet实例,此时ServletContext对象也会被销毁
|--注意服务器启动时servlet对象还没有被创建
servlet之适配器理念:
|--在实际开发中,我们所编写的servlet类在实现了servlet接口后多数情况只使用service方法
|--故为了减少代码冗余,我们通常会编写一个通用的抽象类,令我们编写的servlet类去继承该抽象类
|--该抽象类又称为适配器
|--由该抽象类实现servlet接口
|--将service方法抽象化令子类强制实现
|--其他用的较少的方法则可以直接在该通用接口中实现,若子类有特殊需要再进行重写
|--考虑到子类中有可能使用到ServletConfig对象,适配器中单独定义了成员变量用来存储init中的ServletConfig对象并通过getServletConfig方法进行公开
|--ServletConfig对象中包含了获取web.xml中各项数据的方法
|--为了避免子类重写原生的init方法破环ServletConfig对象的赋值,我们通常将原生init方法设为final方法禁止子类的重写
|--考虑到子类有时确实需要往init方法中添加内容,我们通常定义一个公开的方法供子类继承,然后在init方法中调用这个方法
|--注意tomcat已经为我们提供了这个适配器类,名为GenericServlet
|--但在B/S项目中,又为我们有针对性提供了二级适配器HttpServlet,该类继承了GenericServlet适配器
|--故在B/S项目中我们只需要让自定义servlet类继承并实现HttpServlet适配器即可
Http协议格式规定:
|--请求格式:请求行 + 请求头 + 空白行 + 请求体
|--请求行由请求方式 + URI + Http协议版本号组成
|--注意URI表示统一资源标识符,而URL是统一资源定位符
|--响应格式:状态行 + 响应头 + 空白行 + 响应体
|--其中状态行由协议编号 + 状态码 + 状态描述信息组成
Get和POST请求的区别:
|--Get请求发送数据的时候,数据会通过?挂在URL的尾巴上
|--可以理解为Get请求是在请求行中发送的数据
|--POST请求发送的数据放在请求体中,故不会显示在URL地址中
|--Get请求只能发送少量的字符串数据,且不同的浏览器对其格式还有特别的要求
|--Post请求可以发送任何类型的数据,理论上没有量的限制
|--实际开发中我们使用Get请求进行访问类型的操作,使用Post请求进行传输类型的操作
|--Get请求带有缓存机制
|--目的是为了访问连续同一资源资源的时候可以更高效
|--如果不想使用Get的缓存机制,可以在请求的URL路径中拼上一个变量,如时间戳
|--Get请求的缓存机制与其一般用来做访问操作相呼应
|--Post请求不带有缓存机制
|--Post请求不具有缓存机制与其一般用来做传输操作相呼应
HttpServletRequest中的常用方法:
|--获取操作
|--Map<String,String[]> getParameterMap(),以Map集合的方式获取所传递的所有数据
|--Enumeration<String> getParameterNames(),获取所传递数据的所有属性值(即key值)
|--Enumeration为迭代器,用法跟iterator迭代器大致相同
|--String[] getParameterValues(XX),通过所传递数据的属性值获取对应的value值数组
|--String getParameter(XX),通过所传递数据的属性值获取对应的value值数组的第一个元素
|--Object getAttribute(XX),获取request请求域中XX所绑定的数据
|--String getContextPath(),获取当前servlet在tomcat中所配置的项目名路径(即web根路径)
|--String getMethod(),获取当前所提交请求的提交方式
|--Session getSession(false),获取当前cookie中JSESSIONID对应的session对象,如果没有相匹配的则返回null
|--Session getSession(),获取当前cookie中JSESSIONID对应的session对象,如果没有相匹配的则新建一个返回
|--Cookies[] getCookies(),获取到浏览器传过来的所有cookie对象
|--绑定操作
|--setAttribute(XX,XX),向request请求域中绑定数据
|--移除操作
|--removeAttribute(XX),移除request请求域中XX所绑定的数据
|--请求转发
|--getRequestDispatcher(XX).forward(request,response)
|--XX为需要去到的资源在web.xml配置文件中配置的路径
|--forward方法用于将当前servlet对应的request和response对象传递到即将转发的资源中去
|--该方法常配合绑定操作达到不同servlet中数据共享的作用
|--因为共用一个request和response的原因,故使用转发时产生的页面变化不会改变当前的URL地址
|--设置所获取数据的编码格式
|--setCharacterEncoding(XX),XX为需要设置的编码格式
|--注意该方法只能设置请求体中的编码格式,故只能解决POST方法中的乱码问题
|--GET方法中的乱码问题tomcat8以后默认帮我们解决了
HttpServletResponse中的常用方法:
|--设置操作
|--设置响应数据的编译类型和编码格式
|--setContentType(XX;charset=YY")
|--XX为需要设置的编译类型,常为text/html
|--YY为需要设置的编码格式,常为UTF-8
|--设置响应码
|--setStatus(XX),XX为响应码
|--设置响应头中的属性及数据
|--setHeader(XX,YY),XX为属性名,YY为属性值
|--将所创建的cookie对象添加到浏览器的cookie中
|--addCookie(XX),XX为cookie对象
|--获取操作
|--getWriter(),得到字符输出流对象,通过该对象可以调用print或者write方法进行页面数据输出
|--getOutputStream(),得到字节输出流对象,通过该对象可以调用print或者write方法进行页面数据输出
|--注意如果改变了默认响应编码格式,则用字节流输出时会报错
|--重定向
|--sendRedirect(XX),XX为需要重新定向的新路径
servlet的注解式开发:
|--通过在每个servlet类上方使用 @WebServlet注解的方式代替在web.xml中进行servlet映射关系的配置
|-- @WebServlet注解中常用的属性
|--name:用来指定servlet的别名,不写的话服务器也会隐式自动生成一个
|--urlPatterns:属性值为一个数组,用来设置该servlet在前端页面中所映射的URL地址
|--value:属性值为一个数组,用来设置该servlet在前端页面中所映射的URL地址
|--与urlPatterns属性不同,如果注解中只有一个value属性,且属性中仅有一个属性值时,可以省略该属性名
|--loadOnStartUp:属性值为数值,用来指定是否要在服务器一启动时加载该servlet,数值为加载优先级
解决servlet类爆炸问题:
|--将多个操作的映射路径指向同一个servlet类
|--在servlet类中通过getServletPath方法获取到每个操作对应的具体URI
|--通过每个操作对应的具体URI调用方法执行对应的操作
|--可以简单理解为将多个servlet变成多个方法,由一个servlet类统管并调用这些方法实现功能
JSP注意事项:
|--在服务器启动时,会自动将JSP文件解析成对应的java文件进行编译
|--在JSP中写的html内容,最终都会用java中的输出流语法打印到页面上
|--可以将JSP理解成一个servlet,实际上它最终也确实会解析成一个servlet
|--JSP的常用基础语法
|--<%XXXX%>:服务器在解析JSP文件时会将该语法所包裹的内容视为java代码来执行
|--注意该java代码最终是解析到对应java文件的service方法中
|--<%--XXXX--%>:JSP的专业注释语法,被该语法包裹的内容不会被解析到对应的java文件中
|--<%!XXXX%>:服务器在解析JSP文件时会将该语法所包裹的内容视为java代码来执行
|--注意该java代码最终是解析到对应java文件的类体中
|--受益于服务器对JSP特殊的解析原理,JSP中的java代码可以采用多个<%XXXXX%>或<%!XXXX%>进行切割
|--<%=XXXX%>:JSP的专业输出语法,可以理解为用=代替了out.write(XXXX)
|--JSP的常用指令语法
|--<%@ page%>指令:用于设置整个JSP页面的各种属性
|--import属性:指定JSP页面转换成Servlet时需要导入的包
|--language属性:指定JSP页面转换成Servlet后使用哪种语言进行编译
|--contentType属性:设置最终解析到页面上所采用的编码格式,一般都设置为text/html
|--pageEncoding属性:设置最终解析到页面上所采用的字符集格式,一般设置为charset=UTF-8
|--isELIgnored属性:设置当前JSP页面是否开启对EL表达式的识别
|--errorPage属性:设置当前页面出错后跳转的路径
|--<%@ indlude file="XXXX"%>指令:用于引入其他文件
|--注意引入的文件会与当前JSP页面合并后一起转换成对应的servlet
|--<%@ taglib uri="XXX" prefix="YYY"%>指令:用于引入JSTL标签库中的指令
|--XXX用于指定标签文件或者标签库所在的位置
|--YYY用于指定使用该标签库时应该添加的标签前缀
|--注意使用JSTL语法前需要导入对应的包(并且需要添加到服务器中)
JSP中的EL表达式注意事项:
|--三大作用
|--从4大域中取数据(pageContext域、request域、session域、application域)
|--将取出的数据转成字符串
|--将转成的字符串输出到页面上
|--语法格式:${XX}
|--XX为表达式,且不能加双引号(如果EL表达式中的内容为一个字符串,则会默认将其当成普通文本输出)
|--若XX为一个对象,想取出其属性值要确保该属性有对应的get方法
|--若XX为一个map集合对象,想取出其value值直接用map集合对象.key即可
|--EL中的内置对象
|--pageConetext:等同于JSP中的内置对象pageConetext
|--因为EL表达式中不具备request内置对象,如果需要用的话可以通过pageConetext.request进行获取
|--param.XX:等于JSP语法中的request.Parameter(XX),用于获取单值的情况
|--paramValues.XX:等于JSP语法中的request.ParameterValues(XX),用于获取多值的情况
|--initParam.XX:等于JSP语法中的application.getInitParameter(XX),由于获取web.xml中初始化数据
|--XX为初始化数据中的page-name
|--EL表达式获取数据的顺序
|--从小域到大域(即按照pageContext域 -> request域 -> session域 -> application域的顺序进行检索)
|--有实际需求的情况也可以通过${XX.YY}的形式指定从哪个范围中进行检索
|--XX可以为pageScope、requestScope、sessionScope、applicationScope
|--YY为表达式
|--注意EL表达式的核心作用是可以直接从域中取数据
|--注意EL表达式中的+不会进行字符串拼接,只会进行数值运算
|--可以理解为EL表达式会进行一定限度的类型转换
|--注意如果需要忽略单个EL表达,在$符前添加\即可
session会话机制注意事项:
|--session生命周期
|--在同一个浏览器同一个用户访问服务器时进行判断,如果未找到与之匹配的session对象,则新建一个
|--由于服务器无法监测浏览器是否关闭了,所以session只能由我们手动关闭或者等待session的超时机制进行识别销毁
|--session工作原理
|--服务器以Map集合的方式保存session对象,其中key为JSESSIONID(即每个session对象的对应标识符),value为session对象
|--服务器将生成的JSESSIONID响应给浏览器,由浏览器保存到其cookie中
|--浏览器在访问服务器时会自动将所存的cookie绑定上(如果是第一次访问的话则为null)
|--服务器中根据获取到的cookie查找集合,看是否有与该cookie中JSESSIONID匹配的session对象,以此来判别是否为第一次访问
|--URL重写机制
|--针对有些用户会禁用浏览器接收cookie的特殊情况,我们可以通过将cookie拼接到URL路径中以达到一样的效果
|--注意该做法需要对所有路径进行操作,成本很高
|--常用方法
|--setAttribute(XX,XX):往session对象中绑定属性
|--getAttribute(XX):获取session对象中绑定的属性值
|--removeAttribute(XX):移除session对象中指定的属性
|--invalidate():销毁获取到的这个session对象
|--注意session是一种位于服务器端的存储机制
cookie机制注意事项:
|--cookie只有一个有参构造,且所传参数最终会以key-value的形式存储
|--常用方法
|--setMaxAge(XX):对cookie对象的生存方式进行设置
|--XX>0时表示该cookie对象会存储到硬盘中,并在XX秒后失效
|--XX=0时表示删除该cookie对象
|--XX>0时表示该cookie对象只会存储在浏览器的运行内存中
|--setPath(XX):设置cookie在XX路径及其子路径下才会被携带
|--如果没有设置的话默认在cookie生成路径的父路径及该父路径的所有子路径下才会被携带
|--getValue():获取当前cookie对象中属性的属性名
|--getValue():获取当前cookie对象中属性的属性值
|--注意cookie是一种位于浏览器端的存储机制
Filter过滤器注意事项:
|--过滤原理
|--如果服务器接收到的请求路径同时匹配到过滤器和servlet,一定先执行过滤器再执行servlet
|--一个java类必须实现Filter接口中的所有方法(即init、doFilter、destroy)才能被称为过滤器类
|--init():仅在过滤器对象被创建时执行一次
|--doFilter():只要用户所发的请求路径符合该过滤器负责的路径,就执行一次
|--要想让该过滤器放行需要在该方法中通过FilterChain对象调用doFilter(ServletRequest对象,ServletResponse对象)方法
|--因为采用的是调用方法的形式跳转至servlet,故对应的servlet执行完毕后依旧会回到过滤器中
|--这也是为什么过滤器能同时在servlet前和servlet后进行过滤的原因
|--destroy():仅在过滤器对象被销毁之前执行一次
|--注意过滤器类想在服务器运行过程中发生效用必须在web.xml文件中进行配置(具体配置与servlet配置大致相同)
|--filter-mapping越靠上的过滤器优先级越高
|--过滤器的注解式开发
|--可以采用在过滤器类上加 @WebFilter(需要过滤的路径)注解的方式代替在web.xml中对过滤器的配置
|--此时会自动根据过滤器类名判断过滤器的优先级
|--注意Filter过滤器对象默认在服务器启动时创建
Listener监听器注意事项:
|--一个java类必须实现或重写XX接口中的所有方法才能被称为监听器类,XX为各种监听器的名称
|--注意监听器类想在服务器运行过程中发生效用必须在web.xml文件中进行配置
|--监听器的注解式开发
|--可以采用在监听器类上加 @WebListener注解的方式代替在web.xml中对监听器的配置
|--常用监听器
|--ServletContextListener:用于监测ServletContext对象是否创建
|--ServletRequestListener:用于监测ServletRequest对象是否创建
|--HttpSessionListener:用于监测HttpSession对象是否创建
|--ServletContextAttributeListener:用于监测ServletContext对象中属性的变化
|--ServletRequestAttributeListener:用于监测ServletRequest对象中属性的变化
|--HttpSessionAttributeListener:用于监测HttpSession对象中属性的变化
|--HttpSessionBindingListener:用于监测HttpSession对象中是否添加了指定类型的属性
|--故该监听器一般由bean类负责实现
|--注意该监听器不需要在web.xml文件中进行配置也不需要添加注解
解决javaWeb中的事务问题:
|--开发中常将Connection对象绑到ThreadLocal对象上解决事务问题
|--通过ThreadLocal对象的set(XX)方法可以往其身上绑值
|--通过ThreadLocal对象的get()方法可以从其身上取值
|--注意在关闭Connection对象时要记得将ThreadLocal对象身上绑的Connection对象移除
|--通过ThreadLocal对象的remove()方法进行移除
|--不移除的话可能会报连接已关闭的错误(该错误可以结合线程池进行理解)