如何从在其他服务器上运行的AngularJS应用程序调用Spring Boot REST API?具体来说,我该如何修改以下代码来实现此目的?
我正在使用此链接上的教程来学习Spring Boot 。该应用程序的第一部分和第二部分运行完美。在本教程的第三部分(位于此链接)中,我们将REST api移动到另一个资源服务器,该服务器的原型为localhost:9000
。
该教程使groovy中的资源服务器应用程序成为现实,但是我试图将其修改为Java。
localhost:9000
定义/home/username/workspacename/resource/src/main/java/com/example/ResourceApplication.java
如下所示时,我可以访问Web服务。
但是,正在运行的AngularJS应用localhost:8080
无法从访问Web服务localhost:9000
。当我再添加CorsFilter.java
如下图所示,然后重新启动与服务kill $(lsof -t -i:9000)
和mvn spring-boot:run
,我无法再查看的数据localhost:9000
,我也我仍然无法访问在该应用的Web服务localhost:8080
。
我没有对代码进行任何其他更改,我停在了CorsFilter.java
创建教程并重新启动应用程序的那一刻。那么,如何更改下面的代码以localhost:9000
从gui应用程序访问Web服务localhost:8080
?
资源服务器中两个更改的类的代码如下:
/home/username/workspacename/resource/src/main/java/com/example/ResourceApplication.java
是:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@SpringBootApplication
@RestController
public class ResourceApplication {
@RequestMapping("/")
public Map<String,Object> home() {
Map<String,Object> model = new HashMap<String,Object>();
model.put("id", UUID.randomUUID().toString());
model.put("content", "Hello World");
return model;
}
public static void main(String[] args) {
SpringApplication.run(ResourceApplication.class, args);
}
}
/home/username/workspacename/resource/src/main/java/com/example/CorsFilter.java
是:
package com.example;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class CorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
response.setHeader("Access-Control-Max-Age", "3600");
if (request.getMethod().equals("OPTIONS")) {
try {chain.doFilter(req, res);}
catch (IOException e) {e.printStackTrace();}
catch (ServletException e) {e.printStackTrace();}
}
else { }
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
GUI应用程序中hello.js
文件的代码为:localhost:8080
angular.module('hello', [ 'ngRoute' ])
.config(function($routeProvider, $httpProvider) {
$routeProvider.when('/', {
templateUrl : 'home.html',
controller : 'home'
}).when('/login', {
templateUrl : 'login.html',
controller : 'navigation'
}).otherwise('/');
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
})
.controller('home', function($scope, $http) {
$http.get('http://localhost:9000/').success(function(data) {
$scope.greeting = data;
})
})
.controller('navigation',
function($rootScope, $scope, $http, $location) {
var authenticate = function(credentials, callback) {
var headers = credentials ? {authorization : "Basic "
+ btoa(credentials.username + ":" + credentials.password)
} : {};
$http.get('user', {headers : headers}).success(function(data) {
if (data.name) {
$rootScope.authenticated = true;
} else {
$rootScope.authenticated = false;
}
callback && callback();
}).error(function() {
$rootScope.authenticated = false;
callback && callback();
});
}
authenticate();
$scope.credentials = {};
$scope.login = function() {
authenticate($scope.credentials, function() {
if ($rootScope.authenticated) {
$location.path("/");
$scope.error = false;
} else {
$location.path("/login");
$scope.error = true;
}
});
};
$scope.logout = function() {
$http.post('logout', {}).success(function() {
$rootScope.authenticated = false;
$location.path("/");
}).error(function(data) {
$rootScope.authenticated = false;
});
}
});
正在进行的研究:
按照@meriton的要求,我在firefox中打开了开发人员工具,然后请求localhost:8080
。当我放大到“网络”选项卡上的GET请求的响应标头(用于localhost:9000
嵌入到请求中的调用)时localhost:8080
,我得到了以下请求标头:
Access-Control-Allow-Headers: x-requested-with
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Content-Length: 0
Date: Tue, 08 Dec 2015 00:41:01 GMT
Server: Apache-Coyote/1.1
access-control-allow-origin: *
Network
标签中还显示了以下请求标头:
Host: localhost:9000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8080/
Origin: http://localhost:8080
Connection: keep-alive
过滤器是Servlet的拦截器,可以选择处理请求本身,也可以使用将其传递给过滤器链中的下一个过滤器或servlet chain.doFilter(req, res)
。您的过滤器仅传递选项请求,所有其他请求(例如GET请求)都不会传递或以其他方式响应:
if (request.getMethod().equals("OPTIONS")) {
try {chain.doFilter(req, res);}
catch (IOException e) {e.printStackTrace();}
catch (ServletException e) {e.printStackTrace();}
}
else { }
由于从未写入响应,因此它保持为空,这说明了服务器答复的0KB响应。
为了解决此问题,您应该正确翻译示例代码,即教程代码
if (request.getMethod()!='OPTIONS') {
chain.doFilter(req, res)
} else {
}
应该成为
if (!request.getMethod().equals("OPTIONS")) {
chain.doFilter(req, res)
} else {
}
(请注意否定!)或更好的选择
if (request.getMethod().equals("OPTIONS")) {
// preflight request
} else {
chain.doFilter(req, res)
}
但是,使用Spring MVC提供的CORS-Support可能比自己实现更容易。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句