您的位置:首页 > 其它

【web基础】servlet进阶

2018-02-21 12:02 190 查看

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()

容器调用这个方法来表明一个过滤器正在从服务中移除

过滤器示例

类似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;
H
4000
ttpServletResponse 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中配置

监听器加载顺序

启动服务器->监听器->过滤器->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 发生变化。

0: 请求未初始化

1: 服务器连接已建立

2: 请求已接收

3: 请求处理中

4: 请求已完成,且响应已就绪

status200: "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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: