js使用xhr发送原生ajax请求 | 服务端配置允许跨域

文章提供了POST和GET两种AJAX请求的JavaScript实现,包括创建XMLHttpRequest对象、设置请求头、发送数据和处理响应。同时,讨论了服务端允许跨域的两种策略:通过定义过滤器和使用@CorsOrigin注解。这两种方式都涉及到CORS(跨源资源共享)配置,以允许不同源的请求访问资源。

目录

post请求例子:

get请求例子:

服务端配置允许跨域:


post请求例子:

<script type="text/javascript">
  var obj = document.getElementById("btn");
  var responseMsg = document.getElementById("responseMsg");
  /*【这是在做页面倒计时效果:】*/
  obj.onclick = function () {
    //1.创建对象
    var xhr;
    if (window.XMLHttpRequest) {//普通浏览器
      xhr = new XMLHttpRequest();
    } else {//老版本IE
      xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //2.监听服务器响应
    xhr.open("post", "http://127.0.0.1:7778/getJsonData", true);//true开启异步
    //3.收数据,
    //监控请求状态,监控服务器响应:每当 readyState 发生变化时就会调用 onreadystatechange 函数。【参考https://www.w3school.com.cn/js/js_ajax_http_response.asp】
    //当 readyState 为 4,status 为 200 时,响应就绪:
    xhr.onreadystatechange = function () {
      if (this.readyState == 4 && this.status == 200) {//固定写法
        responseMsg.innerText = this.responseText;
      } else {
        console.log('Error: ' + xhr.status);
      }
    }
    // 设置超时时间
    xhr.timeout = 3000;
    // 设置超时以后的处理函数
    xhr.ontimeout = function () {
      console.log('请求超时了!')
    }
    // 设置请求头发送json数据
    xhr.setRequestHeader('Content-Type', 'application/json');
    //4.发数据:
    var data = {name: 'John', age: 30};
    xhr.send(JSON.stringify(data));
  }
</script>

get请求例子:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
	body{
		background-color: #1f1f2b;
	    color: #fff;
	}
	.box{
		width:400px;
		margin:180px auto;
		padding:30px;
		background:rgba(255,255,255,0.15);	/* 0.15透明度   0不透明-1全透明  */
		box-shadow:0px 0px 50px 0px #fae;		/*内发光:  50px是模糊距离 */
		border-radius:35px;
	}
	h3{
		text-align:center;
		box-shadow:0px 0px 10px 0px #bfa;
		border-radius:5px;
	}
	.context{
		background:rgba(288,144,16,0.08);
		height:120px;
	}
	.lmn{
		margin-top:3px;
		padding-left:30px;
		padding-top:10px;
	}
	div:nth-child(3){
		margin-left:130px;
	}
	input{
		border:none;	
	}
	a{
		color:#e1ba11;
		margin-left:5px;
	}
	button{
		outline:none;
		background-color:#bfa;
		padding:3px;
		border-radius:10px;
	}
	button:hover{
		box-shadow:0px 0px 10px 0px #bfa;
	}
</style>
</head>
<body>
	<div class="box">
		<h3>短信验证码</h3>
		<div class="context">
			<div class="lmn">手机号码:<input type="text" id="phone"/></div>
			<div class="lmn"><input type="text" id="code"/><a href="javascript:void(0);" id="getCode">获取验证码</a></div>
			<div class="lmn"><button onclick="validate()">校验</button></div>
		</div>
	</div>
</body>
<script type="text/javascript">
	var obj = document.getElementById("getCode");
	var flag = 60 ;//全局变量
	/*【这是在做页面倒计时效果:】*/
	obj.onclick=function(){
		if(flag<60){
			return;//避免多次触发
		}
					
		/* ★☆★【Ajax发送手机号,接收验证码】---------------------------------------------------------------------------------------------------------------------
		         【 原生js的ajax】: */
		//1.
		var xhr = new XMLHttpRequest();
		//2.准备数据:
		xhr.open("get","GetYanzhengmaServlet?phone="+document.getElementById("phone").value,true);//true开启异步
		//3.收数据,
			//监控请求状态,监控服务器响应:每当 readyState 发生变化时就会调用 onreadystatechange 函数。【参考https://www.w3school.com.cn/js/js_ajax_http_response.asp】
							//当 readyState 为 4,status 为 200 时,响应就绪:
		xhr.onreadystatechange=function(){
			if (this.readyState == 4 && this.status == 200) {//固定写法
			   //alert(this.responseText);//响应的文本信息。   由于在GetYanzhengmaServlet.java未写响应,故注释
			}
		}
		//4.发数据:
		xhr.send(null);	
		
		/*[]*/
		timer();//调用自定义方法
	}	
	
	//计时器
	function timer(){
		flag--;
		obj.innerText=flag+"秒后验证码失效";
		if(flag<=0){
			obj.innerText="获取验证码";
			flag = 60;//flag重置为60
		}else{
			setTimeout("timer()",1000);//【✔递归调用 函数【setTimeout(,)】】1000=1秒
		}	
	}
	
	
	/*★☆★【验证填入输入框的验证码是否和java代码生成的验证码一致:-----------------------------------------------------------------------------------------------------】
	自定义方法[已在<button onclick="validate()">绑定了onclick事件validate函数]:*/
	function validate(){
		//[[加个判断]]:
		if(flag==60){
			return;//避免倒计时结束后  触发验证
		}
		//1. 【 原生js的ajax】:
		var xhr = new XMLHttpRequest();
		//2.准备数据:
		xhr.open("get","ValidateServlet?code="+document.getElementById("code").value,true);//true开启异步
		//3.收数据,
			//监控请求状态,监控服务器响应:每当 readyState 发生变化时就会调用 onreadystatechange 函数。【参考https://www.w3school.com.cn/js/js_ajax_http_response.asp】
							//当 readyState 为 4,status 为 200 时,响应就绪:
		xhr.onreadystatechange=function(){
			if (this.readyState == 4 && this.status == 200) {//固定写法
			   alert(this.responseText);//响应的文本信息
			}
		}
		//4.发数据:
		xhr.send(null);	
	}
	
	
</script>
</html>

服务端配置允许跨域:

方式1:定义过滤器

在Spring Mvc4.2开始推出了@CorsOrigin注解,在4.2之前是通过定义注册过滤器来实现跨域的:

package com.example.sso.client.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {

  @Bean
  public CorsFilter corsWebFilter() {
    //跨域的配置
    CorsConfiguration config = new CorsConfiguration();
    //config.addAllowedOrigin("*");
    //setAllowCredentials(true)时,不能addAllowedOrigin("*");可以addAllowedOriginPattern("*")
    config.addAllowedOriginPattern("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    config.setAllowCredentials(true);//允许带cookie的跨域
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    CorsFilter filter = new CorsFilter(source);
    return filter;
  }

}

方式2:@CorsOrigin

基本介绍:

可以添加到类上或者方法上:

package com.example.sso.client.controller;

import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;

/**
 * @beLongProjecet: jets-aia
 * @beLongPackage: com.example.sso.client.controller
 * @author: sizzled
 * @createTime: 2023/05/25 上午 11:29
 * @description:
 * @version: v1.0
 */
@RestController
public class TestController {
  @PostMapping("/getJsonData")
  //allowCredentials="true"时不能origins = "*"
  @CrossOrigin(allowCredentials="true",originPatterns = "*" /*, origins = "*"*/)
  public String getJsonData(@RequestBody JSONObject json) {
    return "你好啊:" + json.toJSONString();
  }
}

也可以不在类或者方法上加@CorsOrigin注解,配置全局跨域:

package com.example.sso.client.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 解决跨域问题
 */
@Configuration
@CrossOrigin
public class CorsConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            /*.allowedOrigins("*")*/
            .allowedOriginPatterns("*")
            .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
            .allowCredentials(true)
            .maxAge(3600)
            .allowedHeaders("*");
  }
}

可以指定@CrossOrigin(originins ="http:// localhost:9000"),默认情况下,它使方法接受所有域、所有请求头的请求,也可指定仅接受http:// localhost:9000发送来的跨域请求。

在使用此注解时会发生的一些问题:

1. 注解失效问题

此时调用的方法的@RequestMapping中需要声明请求方式 即增加method=RequestMethod.XXX

2.添加注解后session失效问题

此时对应的js的ajax中需要添加xhrFields:{withCredentials:true}(每个ajax中都需要加此属性,以保证session一致)如:

$.ajax({
		type: "post",
		url: server.path + '/user/login',
        //aja携带凭证访问(避免跨域后session失效)
		xhrFields:{withCredentials:true},
		data: {
			username: uName,
			password: pwd
		},
		success: function (msg) {
		    console.log('登录成功');
		},
		error: function (msg) {
			console.log('请求报错!');
		}
})

对于附带身份凭证的请求(withCredentials:true),服务器不得设置 Access-Control-Allow-Origin 的值为“*”。这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 http://foo.example,则请求将成功执行;其次服务器端需要设置Access-Control-Allow-Credentials: true,否则响应内容不会返回给请求的发起者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值