版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LoveHYZH/article/details/79337641
1.过滤器
- Servlet和JSP中的过滤器都是Java类,它们存在的目的如下:
- 在请求访问后端资源时拦截它
- 管理从服务器返回给客户端的响应
- 常用的过滤器类型:
- 认证过滤器
- 数据压缩过滤器
- 加密过滤器
- 触发资源访问事件的过滤器
- 图像转换过滤器
- 登录和验证过滤器
- MIME类型链过滤器
- 令牌过滤器
- 转换XML内容的XSL/T过滤器
过滤器将会被插入进web.xml文件中,然后映射servlet、JSP文件的名字,或URL模式
当JSP容器启动网络应用程序时,它会创建每一个过滤器的实例,这些过滤器必须在部署描述文件web.xml中声明,并且按声明的顺序执行。
- Servlet过滤器方法
一个过滤器就是一个Java类,它实现了javax.servlet.Filter 接口。
javax.servlet.Filter接口定义了三个方法:
- public void doFilter (ServletRequest, ServletResponse, FilterChain)
每当 request/response要通过过滤链时容器会调用这个方法,因为客户端请求链尾的资源 - public void init(FilterConfig filterConfig)
容器调用这个方法来表明一个过滤器被安置在服务中 - public void destroy()
容器调用这个方法来表明一个过滤器正在从服务中移除
- public void doFilter (ServletRequest, ServletResponse, FilterChain)
- 过滤器示例
类似servlet写法,这里只示例注解实现了
package com.huawei.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebFilter(filterName = "FirstFilter", urlPatterns = "/*")
public class FirstFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("Filter starts...");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
if(1!=1){
out.println("IP is illegal");
}else{
out.println("Ip is 合法");
chain.doFilter(req, resp);
}
}
public void init(FilterConfig config) throws ServletException {
System.out.print("初始化filter...");
}
}
- 多个过滤器应用顺序
- 在web.xml中元素的映射顺序决定了容器应用这些过滤器的顺序。要反转应用的顺序,您只需要反转web.xml中元素的定义顺序就行了。
2.监听器
- 什么是监听器
servlet规范当中一个特殊的类,可以监听容器中产生的一些事件并做相应的处理。Listener 对应观察者模式,事件发生的时候会自动触发该事件对应的Listeer。Listener 主要用于对 Session、request、context 进行监控。
8种监听器可以分为三类:
- 第一大类:监听 Session、request、context 的创建与销毁
HttpSessionLister、ServletContextListener、ServletRequestListener - 第二大类:监听对象属性变化
HttpSessionAttributeLister、ServletContextAttributeListener、ServletRequestAttributeListener - 第三大类:监听Session 内的对象
HttpSessionBindingListener、HttpSessionActivationListener
与上面六类不同,这两类 Listener 监听的是Session 内的对象,而非 Session 本身,不需要在 web.xml中配置
- 第一大类:监听 Session、request、context 的创建与销毁
- 监听器加载顺序
- 启动服务器->监听器->过滤器->servlet
- Web服务器按照web.XML中注册顺序来加载Servlet事件监听器
- Web应用程序中只会为每个事件监听器类创建一个实例对象,在编程中可能出现多个线程同时调用一个事件监听器的情况,要注意监听器对象共享同步问题。
- 监听器的实现
<!--wweb.xml配置-->
<!--一般放在servlet之前-->
<listener>
<listener-class>com.huawei.listener.FirstListener</listener-class>
</listener>
下面用注解方式写
package com.huawei.listener;
import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
@WebListener()
public class FirstListener implements ServletContextListener,
HttpSessionListener,ServletRequestListener {
public FirstListener() {
}
//加载context
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
System.out.println("即将启动"+servletContext.getContextPath());
}
//写在context
public void contextDestroyed(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
System.out.println("即将关闭"+servletContext.getContextPath());
}
//创建session
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("新创建一个session"+session.getId());
}
//销毁session
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("销毁一个session"+session.getId());
}
//创建request
public void requestInitialized(ServletRequestEvent req){
HttpServletRequest request = (HttpServletRequest) req.getServletRequest();
String uri = request.getRequestURI();
uri = request.getQueryString() == null ? uri : (uri + "?" + request.getQueryString());
request.setAttribute("dateCreated", System.currentTimeMillis());
System.out.println("IP " + request.getRemoteAddr() + " 请求 " + uri);
}
//销毁request
public void requestDestroyed(ServletRequestEvent req){
HttpServletRequest request = (HttpServletRequest) req.getServletRequest();
long time = System.currentTimeMillis() - (Long) request.getAttribute("dateCreated");
System.out.println(request.getRemoteAddr() + "请求处理结束, 用时" + time + "毫秒. ");
}
}
3.AJAX
什么是AJAX
- AJAX = Asynchronous Javascript And Xml(异步的JavaScript和xml)
- 是一种用于改善用户体验度的技术,实质上是利用浏览器内置对象 (XMLHttpRequest,一般称为ajax对象)向服务器发送异步请求,服务器接收到请求之后处理数据,处理完之后,返回结果,浏览器利用这结果数据部分更新页面,整个过程当中,页面无刷新,不会打断用户的操作。
- AJAX对象在向服务器发送请求时,浏览器不会销毁当前页面,用户可以在页面中继续其他的操作
创建XMLHttpRequest对象——ajax基础
<script>
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
</script>
- 原生js实现ajax
方法 | 描述 |
---|---|
open(method,url,async) | 规定请求的类型、URL 以及是否异步处理请求。 ● method:请求的类型; ● GET 或 POST url:文件在服务器上的位置 ● async:true(异步)或 false(同步) |
setRequestHeader(header,value) | 向请求添加 HTTP 头。 ● header: 规定头的名称 ● value: 规定头的值 |
send(string) send() |
将请求发送到服务器。 ● string:仅用于POST请求 |
GET 还是 POST?
- 与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。然而,在以下情况中,请使用 POST 请求:
- 无法使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST 没有数据量限制)
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
- 下面是 XMLHttpRequest 对象的三个重要的属性:
属性 | 描述 |
---|---|
onreadystatechange | 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。 |
readyState | 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
|
status | 200: "OK" 404: 未找到页面 |
- 原生js写ajax
<script type="text/javascript">
//get异步请求
function change(v1){
var xhr = getXhr();
//添加随机数避免浏览器调用缓存不刷新
xhr.open("get","tajax?t="+Math.random(),true);
xhr.onreadystatechange = function(){
if(xhr.readyState==4){
var map = xhr.responseText;
document.getElementById("div1").innerHTML = map;
}
}
xhr.send();
}
//post异步请求
function testajax() {
var postData = {"name1":"value1","name2":"value2"};
xhr.open("post","tajax",true);
//这个就照着写吧0.0,设置http消息头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
var map = xhr.responseText;
document.getElementById("div1").innerHTML = map;
}
}
xhr.send(postData);
}
</script>
- jQuery堆ajax的支持
$.ajax(options);
options:是一些键值对{key:value,ke:value},其中的回调函数的入参也是可选的
url:请求地址
type:请求方式get/post
data:请求参数
"username=zs&age=10"
{"username":"zs","age":10}
dataType:服务器返回的数据类型
html,text,xml,js,json等
success:请求成功回调函数
function(data,textStatus){
data:服务器返回的数据
textStaus:服务器返回的状态
}
error:请求失败回调函数
function(xhr,e){
xhr:ajax对象
e:服务器返回的状态
}
$.ajax({
"url":"loadCourse.do",
"cache":false,
"type":"post",
"dataType":"json",
"success":function(data){
for(i=0;i<data.length;i++){
var c = data[i];
var $a = $("<a href='javascript:;' id='"+c.id+"'>"+c.courseName+"</a>");
$a.click(clickCourse);
$("#course").append($a);
$("#course").append(" ");
}
$("#course").children('a').first().trigger('click');
},
"error":function(){
alert("错误");
}
});
4.servlet线程安全问题
- servlet线程安全问题产生的原因
在默认的情况下,容器只会为每一个servlet类创建唯一的一个实例,当请求到达容器时,就有可能有多个线程同时访问同一个实例。 - 如何解决
- 加锁(可以对整个service方法加锁,也可以对某一个代码块加锁。建议使用后者。)
- 让servlet实现SingleThreadModle接口容器会为该servlet创建多个servlet对象,每启动一个线程为其分配一个servlet对象。
- servlet属性尽量设置成可读的,不要去修改。final