如何将跨域资源共享与 Spring MVC 4.0.0 RESTful Webservice 集成

Posted

技术标签:

【中文标题】如何将跨域资源共享与 Spring MVC 4.0.0 RESTful Webservice 集成【英文标题】:How to integrate Cross Origin Resource Sharing with Spring MVC 4.0.0 RESTful Webservice 【发布时间】:2015-01-19 07:43:55 【问题描述】:

我有一个简单的 Web 服务返回 JSON 数据。

User Class (com.bargadss.SpringService.Domain) 是 POJO 类包含

用户 ID、名字、姓氏、电子邮件

UserService 类com.bargadss.SpringService.DAO)两大操作

    getAllUser() -> 查询数据库以选择用户表中的所有用户并返回列表用户 getUserById(int user_ID) -> 查询数据库以选择基于ID的特定用户

SpringServiceControllercom.bargadss.SpringService.Controller)如下:

package com.bargadss.SpringService.Controller;

import java.util.List;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.bargadss.SpringService.DAO.UserService;
import com.bargadss.SpringService.Domain.User;


@RestController
@RequestMapping("/service/user/")
public class SpringServiceController 
 UserService userService=new UserService();

 @RequestMapping(value = "/id", method = RequestMethod.GET,headers="Accept=application/json")
 public User getUser(@PathVariable int id)         
  User user=userService.getUserById(id);
  return user;
 

 @RequestMapping(method = RequestMethod.GET,headers="Accept=application/json")
 public List<User> getAllUsers()    
  List<User> users=userService.getAllUsers();
  return users;
 

ListUserControllercom.bargadss.SpringService.Controller)如下:

package com.bargadss.SpringService.Controller;

import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;

import com.bargadss.SpringService.Domain.User;


@Controller
public class ListUserController 

@RequestMapping("/listUsers")
public ModelAndView listUsers()  
    RestTemplate restTemplate = new RestTemplate();
    String url="http://localhost:8080/SpringServiceWithRESTAndJSONExample/service/user/";    
    List<LinkedHashMap> users=restTemplate.getForObject(url, List.class);
    return new ModelAndView("listUsers", "users", users);


@RequestMapping("/dispUser/userid")
public ModelAndView dispUser(@PathVariable("userid") int userid)  
    RestTemplate restTemplate = new RestTemplate();
    String url="http://localhost:8080/SpringServiceWithRESTAndJSONExample/service/user/userid";
    User user=restTemplate.getForObject(url, User.class,userid);
    return new ModelAndView("dispUser", "user", user);
 


CorsFilter (com.bargadss.CORS) 如下:

package com.bargadss.CORS;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;


public class CorsFilter extends OncePerRequestFilter

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException 
    if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) 
        // CORS "pre-flight" request
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.addHeader("Access-Control-Allow-Headers", "Content-Type");
        response.addHeader("Access-Control-Max-Age", "1800");//30 min
    
    filterChain.doFilter(request, response);



web.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
     id="WebApp_ID" version="3.0">
<display-name>SpringServiceWithRESTAndJSONExample</display-name>

<servlet>
   <servlet-name>rest</servlet-name>
  <servlet-class>
         org.springframework.web.servlet.DispatcherServlet
  </servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>rest</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
 <servlet-name>jsp</servlet-name>
 <url-pattern>/WEB-INF/jsp/*</url-pattern>
</servlet-mapping>

<filter>
  <filter-name>cors</filter-name>
  <filter-class>com.bargadss.CORS.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>cors</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

当 AngularJS 从另一个 Web 服务器调用 Web 服务时返回 Error 指代跨域资源共享问题!!!

必须在 Controller 端执行哪些更改才能消除错误?

为了避免这种情况,AngularJS 方面是否需要进行任何更改?

【问题讨论】:

您错过了将“Access-Control-Allow-Origin”标头添加到 servlet 响应的拦截器。参考:patrickgrimard.com/2013/12/12/… @alain.janinm 上面提到的链接很有用,谢谢,但你能解释一下给定的问题吗? 您确定请求来自子域吗? 您所做的 CORS 过滤器允许您的 servlet 处理传入的请求(它实际上在返回给浏览器的响应中添加了一个标头,告诉该请求实际上将继续进行)但是您也有向您返回给客户的 Servlet 响应添加标头(在请求继续执行之后),这是通过拦截器完成的。 【参考方案1】:

查看cors-filter

下载cors-filter-2.1.2.jarjava-property-utils-1.9.1.jar

mvn 依赖

<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>com.thetransactioncompany</groupId>
  <artifactId>java-property-utils</artifactId>
  <version>1.9.1</version>
</dependency>

web.xml

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
 <filter-mapping>
        <filter-name>CORS</filter-name>
    <url-pattern>/*</url-pattern>
 </filter-mapping>

【讨论】:

以上是关于如何将跨域资源共享与 Spring MVC 4.0.0 RESTful Webservice 集成的主要内容,如果未能解决你的问题,请参考以下文章

mvc webapi跨域帖子[重复]

Ajax+Spring MVC实现跨域请求(JSONP)(转)

Ajax+Spring MVC实现跨域请求(JSONP)

如何在 Spring MVC 中为错误响应启用 CORS?

Spring MVC学习(11)—跨域的介绍以及使用CORS解决跨域问题

CORS 和 Spring MVC 服务 - 如何设置跨域主机?