Angular http 和 spring 引导休息服务

Angular http and spring boot rest service

我正在从我的 angular UI 调用 spring 引导 REST 服务。只要 Spring Boot Rest 服务作为 Spring 引导应用程序执行,它就可以正常工作。但是一旦我将它转换为 WAR 文件并部署在 Jboss 6.2.4 服务器上,我得到 404。我看到来自 UI 的 REST 服务调用成功但请求JSON 没有通过。根据请求 JSON,我传递了 2 个字符串和一个上传的 excel 文件。

这是我的 angular UI http 调用

App.service('getHeatMapDataService', ['$http', '$q', function ($http,      $q) {
this.getHeatMapData = function (scope) {
    var url = 'http://localhost:8080/rest-services/fusiontables/upload';
    var deferred = $q.defer();
    $http({
            method: 'POST',
            url: url,
            headers: {
                'Content-Type': undefined
            },
            data: {
                stateCd: scope.stateCd,
                addressExtras: scope.addressExtras,
                uploadFile: scope.upFile
            },
            transformRequest: function (data, headersGetter) {
                var formData = new FormData();
                angular.forEach(data, function (value, key) {
                    formData.append(key, value);
                });

                var headers = headersGetter();
                delete headers['Content-Type'];
                return formData;
            }
        })
        .success(function (data) {
            deferred.resolve(data);
            console.log("Success");
            console.log(data);
        })
        .error(function (data, status) {
            deferred.reject(status);
            console.log("Failed");
        });
    return deferred.promise;
}
}]);

这是我的 Spring 引导 Rest 控制器工作时

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(HeatMapUploadCommand uploadCommand) {
    logger.info("Heat Map Controller invoked " + uploadCommand);
    return null;
}

这是我的上传命令

public class HeatMapUploadCommand {

private String stateCd;
private String addressExtras;
private MultipartFile uploadFile;

我在 Jboss 上部署后,请求仍然命中 Spring 启动应用程序,但随后它的所有请求参数都为空。

这是请求负载

------WebKitFormBoundaryvCCnl3nhIgoW1MwR
Content-Disposition: form-data; name="stateCd"

CA
------WebKitFormBoundaryvCCnl3nhIgoW1MwR
Content-Disposition: form-data; name="addressExtras"

1234
------WebKitFormBoundaryvCCnl3nhIgoW1MwR
Content-Disposition: form-data; name="uploadFile"; filename="CAdata.xlsx"
Content-Type: application/vnd.openxmlformats-    officedocument.spreadsheetml.sheet


------WebKitFormBoundaryvCCnl3nhIgoW1MwR--

我尝试将控制器更改为

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(@RequestParam(value="stateCd") String stateCd,
        @RequestParam(value="addressExtras") String addressExtras,
        @RequestParam(value="uploadFile") MultipartFile file) {
    System.out.println("Heat Map Controller invoked " + stateCd);
    return null;
}

仍然没有运气。这是我得到的回复。

{"timestamp":1464840821648,"status":400,"error":"Bad    Request","exception":"org.springframework.web.bind.MissingServletRequestParameterException","message":"Required String parameter 'stateCd' is not     present","path":"/rest-services/fusiontables/upload"}

我想你错过了 @RequestBody

当您将 $http 与数据 属性 一起使用时,数据会传入 request body

$http({
    method: 'POST',
    url: url,
    data: {
        stateCd: scope.stateCd,
        addressExtras: scope.addressExtras,
        uploadFile: scope.upFile
    },

我认为一旦您添加 @RequestBody,它可能会起作用。

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(@RequestBody HeatMapUploadCommand uploadCommand) {
    logger.info("Heat Map Controller invoked " + uploadCommand);
    return null;
}

你能试试这个 Spring 控制器方法吗:

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(MultipartHttpServletRequest request, HttpServletResponse response) throws IOException {
    String stateCd = request.getParameter("stateCd");
    String addressExtras = request.getParameter("addressExtras");
    ......
    Iterator<String> iterator = request.getFileNames();
    while (iterator.hasNext()) {
            MultipartFile multipartFile = request.getFile(iterator.next());
            .....
    }
    .........
}

和 Angular 服务:

App.service('getHeatMapDataService', ['$http', '$q', function ($http,$q) {
  this.getHeatMapData = function (scope) {
    var url = 'http://localhost:8080/rest-services/fusiontables/upload';
    var deferred = $q.defer();
    var formData = new FormData();
    formData.append('stateCd', scope.stateCd);
    formData.append('addressExtras', scope.stateCd);
    formData.append('file', scope.upFile);

    $http.post( url, formData, {
        headers: { 'Content-Type': undefined },
        transformRequest: angular.identity
    }).success(function (result) {
        console.log('200');
    }).error(function () {
        console.log('400-500');
    });
    return deferred.promise;
  }
}]);

终于想通了。

我必须添加一个 Multipartresolver bean。

@Configuration
public class WebConfig extends WebMvcAutoConfiguration {
@Bean
public MultipartResolver multipartResolver() {
    return new CommonsMultipartResolver();
}

}

这解决了问题。似乎当我 运行 它作为 spring 引导应用程序时,spring 已经处理了它但是当部署为 WAR 文件时应该配置这个 bean