Angular http和Spring Boot Rest服务

4
我正在从我的Angular用户界面调用Spring Boot的REST服务。只要Spring Boot Rest服务作为Spring Boot应用程序执行,它就能正常工作。但是,一旦我将其转换为WAR文件并在Jboss 6.2.4服务器上部署,我就会遇到404错误。我发现来自UI的REST服务调用成功,但请求的JSON没有被传递。在请求的JSON中,我传递了两个字符串和一个上传的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 Boot 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 Boot应用程序,但是所有的请求参数都为null。

以下是请求载荷

------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"}
3个回答

3

我认为你漏掉了@RequestBody

当你使用$http的data属性时,数据会被传递到请求体(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;
}

现在我收到了HTTP状态码415不支持的媒体类型。 {"timestamp":1464874683832,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message":"不支持内容类型'multipart/form-data;boundary=----WebKitFormBoundarymRKqwcUfa6CJzALs;charset=UTF-8'","path":"/rest-services/fusiontables/upload"} - tindu edward

1

终于搞清楚了。

我需要添加一个Multipartresolver bean。

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

}

那样问题就解决了。看起来当我将其作为Spring Boot应用程序运行时,Spring已经处理了它,但是当部署为WAR文件时,应该配置此bean。

0

您能尝试一下这个Spring Controller方法吗:

@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;
  }
}]);

那似乎没起作用。所有字段仍然返回 null。 - tindu edward
你获取了哪些空字段?请求载荷中是什么样子? - Rana_S
我在问题中包含了请求有效载荷。当我将整个内容作为@RequestBody字符串获取并打印出来时,它会在控制器中打印出来。但是当我使用request.getParameter("stateCd")时,它返回null。关于Angular服务,我也尝试过...但结果相同。似乎这是因为控制器无法识别请求有效载荷的内容类型。 - tindu edward

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接