jquery ajax 调用 spring boot 接口 发送json数据示例,兼容跨域调用,解决maven项目中引用本地lib目录的jar包时打包失败的问题
本文主要解决三个问题:
1.解决maven项目中引用本地lib目录的jar包时打包失败的问题
2.解决spring boot开发的微服务接口中的跨域问题
3.ajax 发送json数据的问题
昨天研究 office 外接程序开发时,发现在插件中调用后台由 Spring boot 开发的接口并传递json时总是失败,调试了半天,尝试了$.ajax,$.post等方法服务端均无法获取到正确的请求,发送到后端的请求的格式是application/www-urlencode,而后端接受的是application/json格式的数据,由于用postman测试接口可以正常返回,应该可以说明后台接口没有问题。
1.解决maven项目中引用本地lib目录的jar包时打包失败的问题
其实在一开始编写后台接口时,也遇到了一些问题,因为接口中引用了一个项目本地的lib目录中的jar包,而这个jar包并未用maven管理,所以调试和打包上遇到了一些问题,以前使用mvn clean install就可以完成的动作,现在一直报错,在pom中这样修改就可以解决了:
<build> <!-- 加上下面的,mvn命令会报错,现在直接调试完毕后,mvn package即可--> <resources> <resource> <directory>lib</directory> <targetPath>/BOOT-INF/lib/</targetPath> <includes> <include>**/*.jar</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build>
2.解决spring boot开发的微服务接口中的跨域问题
由于服务端日志中一直观察不到ajax调用的正确请求,于是祭出终极大杀器——抓包,打开WireShark,选择对应的网卡,参数设置成:
ip.dst_host== 你接口服务器的ip && tcp.dstport ==你接口服务监听的端口
抓包后发现,第一个HTTP请求竟然不是POST,而是OPTIONS:
这不是我嘞个大擦了么…… 立马拿出万能钥匙——谷歌搜索引擎开始解决问题,输入关键字“http options request”,看到第一条就应该是我要的答案了:
沿着指路明灯给出的航向继续前进(这里是链接):
OPTIONS
The HTTP OPTIONS
method requests permitted communication options for a given URL or server. A client can specify a URL with this method, or an asterisk (*
) to refer to the entire server.
继续往下翻,看到了这段文字:
Preflighted requests in CORS
In CORS, a preflight request is sent with the OPTIONS
method so that the server can respond if it is acceptable to send the request. In this example, we will request permission for these parameters:
- The
Access-Control-Request-Method
header sent in the preflight request tells the server that when the actual request is sent, it will have aPOST
request method. - The
Access-Control-Request-Headers
header tells the server that when the actual request is sent, it will have theX-PINGOTHER
andContent-Type
headers.
我恍然大悟,原来是跨域调用的问题。那好办了,继续使用搜索引擎解决问题,然后找到了这篇文章:
SpringBoot解决跨域导致的OPTIONS请求问题
主要是使用了文中列出的类,为了防止文章失效,我把类贴在下面,感谢万能的搜索引擎,感谢楼上文章中的作者,感谢MOZILLA!
package cn.sophie.errorword.detect.detectapi.utils; 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; /** * @author sixiweb * @version 1.0 * @date 2021-08-10 01:01 */ @Configuration public class CorsConfig { // 当前跨域请求最大有效时长。这里默认30天 private long maxAge = 30 * 24 * 60 * 60; private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址 corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头 corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法 corsConfiguration.setMaxAge(maxAge); corsConfiguration.setAllowCredentials(true); //用于 token 跨域 return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置 return new CorsFilter(source); } }
另外,需要在application.yml中做一些配置:
spring: mvc: dispatch-options-request: true
运行接口项目,成功之后用postman测试一遍,very OK,接下来 mvn package打包之后,马上上传到服务器上用postman测试一把,一把过就是这么丝滑比那个啥巧克力还要丝滑。
3.ajax 发送json数据的问题
接口没有问题了,接下来就是解决发送的数据的问题了,office 外接程序使用的比较新的版本——基于nodejs、react的,而office的api也是基于promise的,对ajax也稍作改造一下,用一下匿名函数。
// 将在 Word 文档正文中出现的文字进行错别字监测 $.ajax({ type:"POST", url: "http://你的接口服务的ip地址:8082/api/detect", data: JSON.stringify({ 'c': range.text, 's': "",u:"",d:"" }), contentType: "application/json", success: msg => { console.log(msg); }}, error: (_XMLHttpRequest, _textStatus, _errorThrown) => { // on error $("#rst").html(_XMLHttpRequest.readyState + " --> " + _textStatus + " --> " + _errorThrown); }, dataType:"json"});
最后的成品如下:
反思:
为什么在我调试外接程序的时候没有发现这个web页面是在本地的IIS Express中的呢,不然的话,我应该立马就能想到存在跨域问题。
////////////////////////////////
////////Sixi. Let it be.../////
//////////////////////////////