过滤器
过滤器是一种代码重用的技术,它可以改变 HTTP 请求的内容,响应,及 header 信息。过滤器通常不产生响应或像 servlet 那样对请求作出响应,而是修改或调整到资源的请求,修改或调整来自资源的响应。
作用:既可以对请求进行拦截,也可以对响应进行处理。
常见场景:权限检查,日记操作、拦截请求、过滤操作、对请求字符设置编码
使用过滤器解决中文提交数据的乱码问题
public class CharacterEncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String ss= filterConfig.getInitParameter("encoding");
if(StringUtils.nonBlank(ss))
this.encoding=ss.trim();
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws
IOException, ServletException {
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
Web.xml配置
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>com.yan.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
生命周期
Filter 接口是过滤器类必须实现的接口,该接口中有三个方法:
1、init(FilterConfig filterConfig) 该方法是对 filter 对象进行初始化的方法,仅在容器初始化 filter 对象结束后被调用一次,参数 FilterConfig 可以获得 filter 的初始化参数;
2、doFilter(ServletRequest request,ServletResponse response,FilterChain chain) 该方法是 filter 进行过滤操作的方法,是最重要的方法。过滤器实现类必须实现该方法,方法体中可以对 request 和 response 进行预处理。其中 FilterChain 可以将处理后的 request 和 response 对象传递到过滤链上的下一个资源。
3、destroy() 该方法在容器销毁对象前被调用。
应用开发人员通过实现 javax.servlet.Filter 接口并提供一个公共的空参构造器来创建过滤器。该类及构建 Web
应用的静态资源和 Servlet 打包在 Web 应用归档文件中。Filter 在部署描述符中通过元素声明。一个过滤器或一组过滤器可以通过在部署描述符中定义来为调用配置。可以使用 servlet 的逻辑视图名把过滤器映射到一个特定的 servlet,或者使用 URL 模式把一组 Servlet 和静态资源内容映射到过滤器。
在部署描述符中声明的每个在每个 JVM 的容器中仅实例化一个实例。容器提供了声明在过滤器的部署,描述符的过滤器 config,对 Web 应用的 ServletContext 的引用,和一组初始化参数。
过滤器的核心概念是包装请求或响应,以便它可以覆盖行为执行过滤任务。在这个模型中,开发人员不仅可以覆盖请求和响应对象上已有的方法,也能提供新的 API 以适用于对过滤器链中剩下的过滤器或目标 web 资源做特殊的过滤任务。
过滤器可以通过@WebFilter 注解定义或者在部署描述符中使用元素定义。
1、filter-name:用于映射过滤器到 servlet 或 URL
2、filter-class:由容器用于标示过滤器类型
3、init-params:过滤器的初始化参数
容器必须为部署描述符中定义的每个过滤器声明实例化一个 Java 类实例。因此,如果开发人员对一个过滤器类声明了两次,则容器将实例化两个相同的过滤器类的实例。
一旦在部署描述符中声明了过滤器,配置人员使用定义 Web 应用中的 servlet 和静态资源到过滤器的应用。过滤器可以使用元素关联到一个 Servlet。过滤器可以使用风格的过滤器映射关联到一组 servlet 和静态内容。
当使用风格配置元素,容器必须使用路径映射规则决定是否匹配请求 URI。
容器使用的用于构建应用到一个特定请求 URI 的过滤器链的顺序:
-
1)首先按照在部署描述符中的出现顺序匹配过滤器映射。
-
2)接下来按照在部署描述符中的出现顺序匹配过滤器映射。 如果过滤器映射同时包含了
和,容器必须展开过滤器映射为多个过滤器映射(每一个和一个),保持和元素顺序。
通过在部署描述符中使用心得元素,开发人员可以为 filter-mapping 指定是否想要过滤器应用到
请求,当:
1)请求直接来自客户端。可以由一个带有 REQUEST 值的元素,或者没有任何元素来表示。
2)使用表示匹配或的 web 组件的请求分配器的 forward 调用情况下处理请求。可以由一个带有 FORWARD 值的元素表示。
3)使用表示匹配或的 Web 组件的请求分派器的 include 调用情况下处理请求。可以由一个带有 INCLUDE 值的元素表示。
4)使用错误处理指定的错误页面机制处理匹配的错误资源的请求。可以由一个带有 ERROR 值的元素表示。
5)使用异步处理中的异步上下文分派机制对 web 组件使用 dispatcher 调用处理请求。可以由一个带有 ASYNC值的元素表示。
为了保证 MyBatis 中的事务提供,同时管理 SqlSession,实现一次请求响应过程对应一个事务,对应一个SqlSession,处理完成后必须保证 SqlSession 关闭
@WebFilter("*.do")
public class OpenSessionInViewFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws
IOException, ServletException {
try{
chain.doFilter(request,response);
MyBatisSessionFactory.commitTransaction();
} catch (Exception e){
MyBatisSessionFactory.rollbackTransaction();
throw new ServletException(e);
}finally {
MyBatisSessionFactory.closeSession();
}
}
@Override
public void destroy() {
}
}
监听器
Servlet 事件监听器支持在 ServletContext、HttpSession 和 ServletRequest 状态改变时进行事件通知。Servlet上下文监听器是用来管理应用的资源或 JVM 级别持有的状态。HTTP 会话监听器是用来管理从相同客户端或用户进入web应用的一系列请求管理的状态或资源。
Servlet请求监听器是用来管理整个Servlet请求周期的状态。
异步监听器用来管理异步事件。如超时和完成异步处理。
可以有多个监听器类监听每一个事件类型,且开发人员可以为每一个事件类型指定容器调用监听器 bean 的顺序。
监听器类在 Web 应用部署描述符中使用 listener 元素声明。它们根据类名列出的顺序就是它们被调用的顺序。
与其他监听器不同,AsyncListener 类型和监听器可能仅通过编程式注册(使用一个 ServletRequest)。
Web 容器创建每一个监听器类的一个实例,并在应用处理第一个请求之前为事件通知注册它。
在分布式 Web 容器中,HttpSession 实例被限定到特定的 JVM 服务会话请求,且 ServletContext 对象被限定到Web 容器所在的 JVM。分布式容器不需要传播 Servlet 上下文事件或 HttpSession 事件到其他 JVM。监听器类实例被限定到每个 JVM 的每个部署描述符声明一个。
JSP基础
同步混编模式,核心是三大指令:page include taglib、六大动作和九大默认对象。
开发模式
SUN 公司推出 JSP 技术后,同时也推荐了两种 web 应用程序的开发模式,一种是 JSP+JavaBean 模式,一种是 Servlet+JSP+JavaBean 模式。
MVC 模型是一种架构型的模式,本身不引入新功能,只是帮助将开发的结构组织的更加合理,使展示与模型分离、流程控制逻辑、业务逻辑调用与展示逻辑分离。
Model:封装业务逻辑和业务数据,使用 JavaBean 实现
View:显示业务数据和收集客户动作,使用 JSP+JSTL 实现
Controller:流程控制,使用 Servlet 实现
AJAX
AJAX 即 Asynchronous JavaScript And XML 异步 javascript 和 xml,Ajax 核心由 HTML、
JavaScript 技术和 DOM组成。是指一种创建交互式网页应用的网页开发技术。是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
Ajax 包括
1、基于 web 标准 XHTML 和 CSS 进行显示;
2、使用文档对象模型 DOM 作页面的部分更新及动态效果
3、使用 XML 和 XSLT 进行数据交互,目前使用较多的是 JSON,因为 xml 文件解析比较繁琐
4、使用 XMLHttpRequest 进行与网页服务器进行异步资料交换。这个 xhr 已经被纳入到浏览器规范中,所以所有的浏览器都提供了 xhr 的实现,但是不同的浏览器生产商的实现方式不一致
5、使用 JavaScript 将它们绑定在一起
AJAX 原理
客户端发送请求,请求交给 xhr,xhr 把请求提交给服务,服务器进行业务处理,服务器响应数据交给 xhr 对象,xhr 对象接收数据,由 javascript 把数据写到页面上
原生 AJAX 编程
流程:显示一个输入框,用户输入名称后,点击提交,当前页面并不更新,但是异步将用户名提交给 servlet,生成对应的问候信息,页面部分更新进行显示
编程步骤:1、页面事件触发特定函数执行,首先创建 xhr 对象,注意浏览器的差异性
<body>
<div id = "div1">测试AJAX</div>
用户名称:<input id = "username"><input type = "button" onclick="ff()" value="问候">
<script>
var xhr = null;
function ff(){
createXHR()
}
function createXHR(){
if(window.XMLHttpRequest)//针对非IE浏览器
xhr=new XMLHttpRequest()
else if(window.ActiveXObject)//针对版本低的浏览器
//实际上这里的参数根据不同版本的IE浏览器参数不同
xhr=new ActiveXObject("Microsoft.XMLHttp")
}
</script>
2、调用 XMLHttpRequest 中提供的方法和服务器 Servlet之间进行通信
<script>
var xhr = null;
function ff(){
//1、创建xhr对象
createXHR()
if(xhr){//2、打开与服务器的连接
var name = document.getElementById("username").value;//获取用户在<input id = username>中输入的数据
xhr.open('GET','hello.do?username='+name,true);
//3、注册回调事件处理函数
xhr.onreadystatechange=callback;//就是当xhr的readyState发生改变时,自动执行callback函数
//4、发送请求,由于采用的是get方法所以没有协议体数据
xhr.send(null);
}else {
alert('您的浏览器不支持异步操作!')
}
}
</script>
3、定义事件回调函数
function callback(){
//1、检查xhr的响应状态,实际上只关注4
var div1 = document.getElementById("div1")//获取输出显示的元素对象<div id = "div1">
if(4==xhr.readyState){
//2、检查服务器的响应状态码,实际上只关心200
if(200==xhr.status){
//3、可以通过xhr的responseText和responseXML获取服务器的响应值
var ss = xhr.responseText//将响应信息显示在<div id = div1>中
}else{
div1.innerHTML='您访问的地址错误'
}
}else{
div1.innerHTML='数据正在加载中......'
}
}
4、定义服务器端的 Servlet,用于处理客户端请求信息,并生成对应的文本响应
AJAX 是一种前端技术,运行在浏览器中,和服务器所使用的语言、框架等无关。
@WedServlet("hello.do")
public class HttpAction extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException{
String username = req.getParameter("username");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.print("Hello" + username + "!");
writer.flush();
writer.close();
}
}
优点:
可以无需刷新页面,与服务器进行通信
允许依据用户事件来更新部分页面内容
缺点:
没有浏览历史,不能回退
存在跨域问题(同源)
SEO 不友好(搜索引擎优化,对爬虫不友好)
Xhr 中的常见方法:
xhr 的 open 方法 有两三个参数,
第一个参数是什么方法请求服务器来获取数据,其中包括“GET”,“POST”,“SEND”,根据使用场景的不同,切换使用。
第二个参数是位于这个服务器端口上的 server 这个文件内容。
第三个参数是一个 boolean 值,有 true 和 false 来选择是否以异步的方式发送请求。
onreadystatechange 是 xhr 里的一个方法 字面意思为,当 状态 准备 发生 变化 的时候要怎么做,准确的来说,是在你 open 方法调用后,服务器马上要给你送回数据的时候,你可以预先对即将返回的数据 dosomesing。
这时候 xhr 对象里有一个属性名为 readyState(注意 State 的 S 是大写):0,1,2,3,4 会被赋值,这四个状态是依次改变的,0 到 1,1 到 2,2 到 3,3 到 4。 一共四次状态变化,3 和 4 并不是二选一
0 表示还没开始.为这个属性的初始值
1 表示 open 方法开始被调用结束
2 表示 send()方法已经运行结束
3 表示服务器 一部分 数据送回来了 //这一步的时候其实就可以操作数据了,但是不合理
4 表示全部数据已经返回
为了简化 AJAX 编程开发,可以考虑使用面向对象的方式对 ajax 常规操作进行封装
function AjaxObject() {//在 java 中 class AjaxObject{}
this.req = null; //定义属性,XMLHttpRequest req;
//定义成员方法 public void getHttpXMLRequest(){...}
this.getHttpXMLRequest = function () {//public XMLHttpRequest getHttpRequest(){}
if (window.XMLHttpRequest) {
this.req = new XMLHttpRequest();
} else { //
if (window.ActiveXObject) {
this.req = new ActiveXObject("Microsoft.xmlhttp");
}
}
};
//注意:在 js 中进行调用时参数个数可以不一致
this.sendRequest = function (url, params, HttpMethod) {
if (!HttpMethod) { //判断是否有 HttpMethod 参数,如果没有则默认值为 post
HttpMethod = "POST";
}
this.getHttpXMLRequest(); //调用另外的方法创建 xhr 对象
if (this.req) { //如果 xhr 创建成功,则 this.req 不为空,否则可以报错
this.req.onreadystatechange = this.showData; //注册回调事件处理函数
this.req.open(HttpMethod, url, true); // 打开与服务器的连接
//设置请求头参数,用于模拟一个 post 的 form 表单提交数据
this.req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// username=mike&userpass=123
this.req.send(params); //利用协议体传递数据
}
};
this.showData = function () {
};
}