AngularJS调用Spring GET接口成功但页面未加载,求原因
我尝试在AngularJS的scope里调用Spring控制器定义的GET方法来打开页面,接口调用成功了,但页面始终加载不出来。下面是我的相关代码:
AngularJS中触发调用的success回调代码
.then(function successCallback(response) { if (response.status == 204) { // 处理204逻辑 } else if (response.status == 200) { $scope.nredit = { }; $scope.goToView.goToView(); // 在这里调用GET方法 } }
负责调用GET方法的AngularJS scope代码
$scope.goToView = { goToView: function () { $http({ method: 'GET', url: '/mypage', }).then(function successCallback(response) { if (response.status == 400) { alert('Not allowed to view this page!'); } else if (response.status == 200) { // $scope.users = response.data; } }, function errorCallback(response) { alert(JSON.stringify(response)); }); } }
Spring控制器中的GET方法代码
@RequestMapping(value = "/mypage", method = RequestMethod.GET) public ModelAndView goToView(ModelAndView model, HttpServletRequest request, HttpSession userSession) throws IOException { model.setViewName("view"); return model; }
问题原因分析
你这里踩了一个常见的理解误区:$http.get是用来异步获取数据/资源的工具,不是用来触发页面跳转的!
你的Spring控制器返回ModelAndView,本质是让服务器渲染对应的视图模板(比如Thymeleaf、JSP等)并生成完整的HTML页面。但AngularJS的$http请求只会把这个HTML页面的内容作为响应数据接收回来,不会自动帮你跳转到这个页面,也不会替换当前页面的内容——它只是把HTML字符串存在response.data里,而你没做任何后续处理,所以页面自然没变化。
解决方案
根据你的实际需求,分两种情况处理:
情况1:想跳转到服务器端渲染的完整页面
如果你的/mypage是一个独立的服务器端渲染页面(不是Angular单页应用的一部分),那完全不需要用$http请求,直接触发页面跳转即可:
修改AngularJS的goToView方法:
$scope.goToView = { goToView: function () { // 直接跳转到目标页面,这才是打开新页面的正确方式 window.location.href = '/mypage'; } };
或者如果你习惯用Angular的$location服务(需要先在控制器中注入),也可以这么写:
// 先在控制器里注入$location app.controller('YourController', function($scope, $location) { $scope.goToView = { goToView: function () { $location.path('/mypage'); } }; });
这种方式下,浏览器会直接向/mypage发送GET请求,Spring控制器返回的ModelAndView会被服务器渲染成页面并展示给用户,和普通的页面跳转效果完全一致。
情况2:想在Angular单页中加载视图片段
如果你的需求是在当前Angular单页里插入/mypage的内容(而不是跳转到新页面),那需要调整Spring控制器和AngularJS的处理逻辑:
- 修改Spring控制器,返回渲染后的HTML字符串(而不是
ModelAndView):
@RequestMapping(value = "/mypage", method = RequestMethod.GET) public String goToView(HttpServletRequest request, HttpSession userSession) throws IOException { // 这里返回的"view"会被模板引擎渲染成HTML字符串返回 return "view"; }
- 修改AngularJS的
goToView方法,把返回的HTML插入到页面的指定容器中:
$scope.goToView = { goToView: function () { $http({ method: 'GET', url: '/mypage', }).then(function successCallback(response) { if (response.status == 200) { // 假设页面上有一个id为view-container的容器 document.getElementById('view-container').innerHTML = response.data; // 更Angular风格的做法:用ng-bind-html(需要引入ngSanitize模块) // $scope.viewContent = response.data; } }, function errorCallback(response) { alert(JSON.stringify(response)); }); } };
如果用ng-bind-html,需要在页面中添加:
<div ng-bind-html="viewContent"></div>
并且在你的Angular模块中引入ngSanitize:
var app = angular.module('yourApp', ['ngSanitize']);
内容的提问来源于stack exchange,提问作者Kingston

