CORS 使用ajax+servlet实现

主要是针对非IE的CORS实现,因为IE的CORS直接使用XDomainRequest,比较简单,功能也比较简单。在此是针对非IE中如何实现跨源。

主要有两个方面:1.如何使用PreflightRequest实现功能较丰富跨域请求,功能丰富体现在:可以发送自定义头部信息;可以使用get和post以外的方法;可以发送不同类型的主体内容。摘录一段文档:

Unlike simple requests(discussed above),"preflighted" requests first send an HTTP request by theOPTIONSmethod to the resource on the other domain,in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular,a request is preflighted if:

(1)It uses methodsotherthanGET,HEADorPOST. Also,ifis used to send request data with a Content-Typeapplication/x-www-form-urlencoded,multipart/form-datatext/plainrequest sends an XML payload to the server usingapplication/xmltext/xmlispreflighted.
(2)It sets custom headers in the request (e.g. the request uses a header such asx-zd)

Note:Starting inGecko2.0,thetext/plain,application/x-www-form-urlencoded,andmultipart/form-datadata encodings can all be sent cross-site without preflighting. PrevIoUsly,onlytext/plainCould be sent without preflighting.


(参考资料:https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redirectlocale=en-US&redirectslug=HTTP_access_control

源码实例:js部分:

function crosFunc(){
		var xhr=new XMLHttpRequest();
		xhr.onreadystatechange=function(){
			if(xhr.readyState==4){
				if(xhr.status>=200&&xhr.status<=300||xhr.status==304){
				console.log("--->"+xhr.getAllResponseHeaders());//为空,不能访问返回的头信息
					console.log(xhr.responseText);
					console.log(console.log(document.cookie));//username=444  undefined  因为同源策略的影响,访问不到从服务器返回来的cookie
				}
				else{
					alert("cros Failed!");
				}

			}
		}
				if('withCredentials' in xhr){//检测xhr是否支持CORS,如果不支持,说明是ie,就只能使用XDomainRequest进行跨域
				console.log("it is true");
				}
		xhr.open('get','http://202.197.66.228:8083/TestCORS/ServerServlet',true);	
	        xhr.setRequestHeader('x-zd','zd');//发送自定义头部	
		xhr.send(null);		
	}
crosFunc();
</script>
servlet部分:注意红色部分的代码,要在doOptions中加入一些头信息,这样浏览器才会把结果交给js,否则就会出错
public class ServerServlet extends HttpServlet {

	
	public ServerServlet() {
		super();
	}

	
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	
	public void doGet(HttpServletRequest request,HttpServletResponse response)
			throws servletexception,IOException {

		this.execute(request,response);
	}

	public void doPost(HttpServletRequest request,response);
	}
	
	private void execute(HttpServletRequest request,HttpServletResponse resp){
		  resp.setCharacterEncoding("utf-8");		  
		  Cookie [] cs=request.getCookies();
		  System.out.println("cookies:"+( cs==null?0:cs.length));
		 Cookie c=new Cookie("tongguo","true");
		resp.addCookie(c);
		  resp.addHeader("Access-Control-Allow-Origin","http://localhost:8083");//注意此处		   	
		   List<UserInfo> tempt=_getSomeInfos();
		   JSONObject jobj=new JSONObject();
		   jobj.put("rows",tempt);
		   System.out.println(jobj);
		   byte[] jsonBytes;
		try {
			jsonBytes = jobj.toString().getBytes("utf-8");
			resp.setContentLength(jsonBytes.length);  
			resp.getoutputStream().write(jsonBytes);  
			resp.getoutputStream().flush();  
			resp.getoutputStream().close(); 
		} catch (Exception e) {
			// Todo Auto-generated catch block
			e.printstacktrace();
		}  
	}
	 @Override
	protected void doOptions(HttpServletRequest req,HttpServletResponse resp)
			throws servletexception,IOException {
		 resp.addHeader("Access-Control-Allow-Origin","http://localhost:8083");		
		  resp.addHeader("Access-Control-Max-Age","1728000");		
		  resp.addHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS"); 
		  resp.addHeader("Access-Control-Allow-Headers","User-Agent,Origin,Cache-Control,Content-type,x-zd,Date,Server,withCredentials");
//注意此处不要再调用super.dooptions方法	  
		  
	}

	private List<UserInfo> _getSomeInfos() {
			List<UserInfo> result=new ArrayList<UserInfo>();
			UserInfo u=null;
			for(int i=0;i<30;i++){
				
				u=new UserInfo();
				u.setUsername("zhang"+i);
				if(i%2==0){
					u.setSex("Female");
					u.setAddress("四川");
					u.setSchool("CSU");
				}else{
					u.setSex("Male");
					u.setAddress("湖南长沙");
					u.setSchool("CWNU");
				}
				result.add(u);		
			}
			Collection nuCon = new Vector();
			nuCon.add(null);
			result.removeAll(nuCon);
			return result;
			
		}	
}

结果:发出了两次请求。第一次是options请求,第二次是get请求。






2.是使用CORS,发送一些带凭据的跨域请求,所谓的凭据就是一些cookie,HTTP认证什么的。摘录一段文档:

The most interesting capability exposed by bothXMLHttpRequestand Access Control is the ability to make "credentialed"requests that are cognizant of HTTPCookies and HTTPAuthentication information. By default,in cross-siteinvocations,browsers willnotsend credentials. A specific flag has to be set on theobject when it is invoked.

一般认情况下都是不启用带有凭据的跨域,因此如果想要启用的话,只需将XMLHttpRequest的withCredentials属性设置为True,注意此处从服务器返回来的cookie信息以及响应头信息,可以通过浏览器显示出来,但是在js中不能用代码进行访问。

js代码

<script type="text/javascript">
	function crosFunc(){
		var xhr=new XMLHttpRequest();
		xhr.onreadystatechange=function(){
			if(xhr.readyState==4){
				if(xhr.status>=200&&xhr.status<=300||xhr.status==304){
				console.log("--->"+xhr.getAllResponseHeaders());//为空,不能访问返回的头信息
					console.log(xhr.responseText);
					console.log(console.log(document.cookie));//username=444  undefined  因为同源策略的影响,访问不到从服务器返回来的cookie
				}
				else{
					alert("cros Failed!");
				}

			}
		}
				if('withCredentials' in xhr){//检测xhr是否支持CORS,如果不支持,说明是ie,就只能使用XDomainRequest进行跨域
				console.log("it is true");
				}
		xhr.open('get',true);
	setCookie("username","444",12);
	xhr.setRequestHeader('x-zd','zd');
	xhr.withCredentials = "true";//向服务器说明我要发送带凭据的请求
		xhr.send(null);
		
	}
crosFunc();
function setCookie(key,value,hour){
		var _cookie=key+"="+encodeURIComponent(value);
		if(hour>0){
			var date=new Date();
			date.setTime(date.getTime()+hour*3600*1000);
			_cookie+=";expires="+date.toGMTString();
		}
		document.cookie=_cookie;
	}

java代码,只是在doOptionsexecute方法中各加入了同一行代码

resp.addHeader("Access-Control-Allow-Credentials","true");

结果:也是发出了两个请求,options请求和上面的一样,只看get请求:


刷新该页面,可以发现,发出带有cookie的请求:

同时在控制台查看响应的头部,主体内容,和cookie信息:

相关文章

IE6是一个非常老旧的网页浏览器,虽然现在很少人再使用它,但...
PHP中的count()函数是用来计算数组或容器中元素的个数。这个...
使用 AJAX(Asynchronous JavaScript and XML)技术可以在不...
Ajax(Asynchronous JavaScript and XML)是一种用于改进网页...
本文将介绍如何通过AJAX下载Excel文件流。通过AJAX,我们可以...
Ajax是一种用于客户端和服务器之间的异步通信技术。通过Ajax...