基于Spring和Spring MVC实现可跨域访问的REST服务
https://www.tianmaying.com/tutorial/cross-origin-rest-service
Web应用中前端JavaScript访问后端的REST服务默认是不能跨域的,这里的域英文中叫Origin,有时也叫Domain,包含了协议(HTTP/HTTPS),域名和端口号。不能跨域指的是,如果来自http://abc.com:80的JavaScript代码只能访问http://abc.com:80中的资源(HTTP默认端口号为80,注意端口号不同也是不同的域)。大家不妨试一试在自己的JavaScript代码中去访问Google搜索的URL,代码是不能正常运行的。
Same Origin Policy(SOP)是浏览器默认的安全模型,为什么需要SOP呢? 因为如果允许JavaScript代码访问非相同域资源的话,那么安全性将变得完全不可控。举个例子,如果另外一个网址中包含的恶意脚本就可以没有任何防备的加载进来,那就就能随意获取或者恶意修改页面元素Cookie信息等。SOP则保证了所有你访问的资源和服务是来自于你自己的服务器,外部的脚本就不能没有任何障碍得攻击你了。当然这只是基本的安全模型,通过XSS等技术,如果你的代码有漏洞的话,还是可能受到来自不同域的恶意代码的攻击,这里就不展开啦。
但是有时候我们就是希望自己的服务是可以被跨域访问的,我们知道要访问的不同域的远程资源是安全的,这时候SOP反而给我们带来了限制。所以又出现了一些跨域访问的技术,比如JSONP。今天我们就来介绍如何基于Spring来实现可跨域访问的REST服务。
准备工作
今天我们来创建一个接收HTTP GET
请求的REST服务,访问地址是http://localhost:8080/greetin)
,返回的格式为:
{
"id": 1,
"content": "Hello, World!"
}
如果请求中包含name
参数,则会将默认的World
替换为name
的值。比如http://localhost:8080/greeting?name=User
请求则返回:
{
"id": 1,
"content": "Hello, User!"
}
开发环境:
- IDE+Java环境(JDK 1.7或以上版本)
- Maven 3.0+(Eclipse和Idea IntelliJ内置,如果使用IDE并且不使用命令行工具可以不安装)
POM文件:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tianmaying</groupId>
<artifactId>cross-origin-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cross-origin-demo</name>
<description>Demo of enabling Cross Origin Requests for a RESTful Web Service</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
REST服务的实现
Greeting JSON格式的信息对应的模型类为Greeting
类,非常简单。
Greeting.java
package com.tianmaying.crossorigin;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
Controller的实现我们应该也是轻车熟路了。
GreetingController.java
package com.tianmaying.crossorigin;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public @ResponseBody Greeting greeting(
@RequestParam(value="name", required=false, defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
@RequestMapping
标注将/greeting
请求映射到greeting()
方法。
提示
上面的例子中没有指定URL对应的HTTP方法,比如GET
、PUT
、POST
或者DELETE
,这表示所有HTTP方法都映射到这个URL上。如果希望指定特定的方法,可以这样设置@RequestMapping(method=GET)
@RequestParam
将请求参数绑定到greeting()
方法中的参数,该参数不是必须的,如果没有提供,则使用默认值World。
方法的实现创建并返回了一个Greeting
对象,id
通过AtomicLong
来设置,content
则通过一个简单的字符串模板来生成。
REST服务和传统的MVC控制器的一个关键区别在于,REST服务通常并不依赖于一种模板技术(比如JSP、Velocity等)来生成HTML,REST服务只是填充好对象的信息,然后将对象信息转换为JSON字符串直接写入HTTP的响应中。而@ResponseBody
正是来做这件事情的!
而对象转为为JSON这件事情,有了Spring的HTTP消息转换(HTTP Message Converter)的支持可以自动化的完成。只要Jackson 2在类路径中,Spring的MappingJackson2HttpMessageConverter
会自动启用将Greeting
对象转为JSON。
关于Spring MVC的更多内容请大家参考Spring MVC实战入门训练。
跨域支持
接下来是最关键的时候了,之前我们已经实现了一个普通的REST服务,如何支持跨域就在此一举了:)我们只需要增加一个Filter
,在HTTP响应中增加一些头信息,我们通过SimpleCORSFilter
来实现。
SimpleCORSFilter.java
package com.tianmaying.crossorigin;
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.HttpServletResponse;
import org.springframework.stereotype.Component;
@Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
SimpleCORSFilter
在响应中增加了一些Access-Control-*
头。在上面的例子中,设置的头信息表示允许来自任何域的客户端访问POST
, GET
, OPTIONS
和 DELETE
请求,请求的结果将缓存至多3600秒。当然,这只是一个很简单的跨域支持filter,大家可以根据需要进行更多的设置,比如只支持来自特定域的请求访问特定的资源。
测试
最后我们通过main()
函数将这个SpringBootApplication
Run起来:
App.java
package com.tianmaying.crossorigin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
相关推荐
"Spring MVC REST Demo"是一个示例项目,旨在展示如何在Spring MVC框架中实现RESTful Web服务。下面将详细讨论Spring MVC与RESTful API的结合,以及如何创建和测试此类服务。 首先,Spring MVC是Spring框架的一部分...
Spring 3.0 MVC 实现 REST 代码是一个关于构建基于 RESTful 风格的 Web 服务的示例。REST(Representational State Transfer)是一种架构风格,常用于设计网络应用程序,强调通过统一资源标识符(URI)来访问资源,...
REST(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,它基于HTTP协议,实现了资源的分布式管理和访问。本教程将通过一个简单的例子,讲解如何利用Spring MVC创建REST服务。 首先,...
- 如果涉及到数据库操作,可以结合Spring Data JPA简化数据库访问,通过`@Repository`、`@Entity`、`@Service`和`@Transactional`等注解实现ORM。 通过"spring mvc rest基础学习demo",初学者可以快速掌握如何使用...
在本示例中,我们将深入探讨如何利用Spring MVC框架构建RESTful API,主要涉及`employeeDS.java`这个可能的数据服务类以及与`rest_spring_mvc`、`spring_mvc`和`spring_rest`相关的概念。`spring-rest.rar`是一个...
Spring 3.0 MVC 和 REST 是 Java Web 开发中的重要组成部分,它们为构建现代、高效的应用程序提供了强大的框架支持。本文将深入探讨这两个概念以及如何通过一个入门实例来理解它们。 Spring MVC(Model-View-...
"SPRING-MVC-MQ-CXF-REST_Demo"这个项目很可能是用来演示如何在同一个应用中整合Spring MVC、MQ、CXF和REST技术。项目可能包含了以下部分: 1. Spring MVC配置:展示了如何设置DispatcherServlet、视图解析器以及...
在这个小例子中,我们将探讨如何使用Spring MVC来实现REST接口。 首先,让我们理解Spring MVC的基本架构。Spring MVC通过DispatcherServlet作为前端控制器,接收HTTP请求,然后根据请求映射找到相应的Controller...
Spring MVC 是一个强大的Java Web开发框架,用于构建可维护、...通过理解Spring MVC的MVC模式,掌握Web服务的基本原理,以及学习如何在Spring环境中配置和调用Web服务,开发者可以构建更加灵活和可扩展的Web应用程序。
10. **国际化和本地化**:通过消息源和LocaleResolver,Spring MVC可以轻松实现应用的多语言支持。 在实际开发中,我们可以通过Maven或Gradle等构建工具将Spring MVC 4.2.3依赖引入项目。同时,使用IDE如IntelliJ ...
这些内容是作者个人总结所的,主要描述了如何使用Spring MVC搭建Rest服务的全过程,并提供了整个搭建过程的源码。整个搭建过程中使用了Jetty、JAXB2.0和Spring等相关框架和技术,希望下载的人能够对这些技术有所了解...
毕设&课设&项目&实训基于Spring4 mvc rest+JPA2实现的物联网REST服务后台,测试的网页客户端界面设计采用了Bootstrap3设计 【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、...
【标题】"mavin spring4 mvc mybatis 整合 带事务,REST风格" 涉及到的是一个基于Java技术栈的Web应用程序开发,整合了Maven、Spring4 MVC、MyBatis框架,并且实现了RESTful API设计以及事务管理。下面将对这些关键...
7. **CORS支持** - 对于跨域资源共享(CORS),Spring MVC提供了`CorsRegistry`和`CorsConfiguration`来配置允许哪些来源进行访问。 8. **Validation** - 使用JSR-303/JSR-349提供的注解进行数据验证,例如`@Not...
在Spring MVC中,我们可以利用其内置的支持轻松地构建REST服务。 首先,要创建REST服务,你需要了解以下几个核心概念: 1. **URI(Uniform Resource Identifier)**:REST中的每个资源都有一个唯一的URI,用于标识...
Spring Web MVC是一种基于MVC模式的轻量级Java Web应用框架,它是Spring框架的一部分,主要用于简化Web层的开发。Spring Web MVC允许开发者将应用程序分为三个主要组件:模型(Model)、视图(View)和控制器(Controller...
2. **Spring MVC与REST**:Spring MVC提供了一套优雅的方式来实现RESTful服务。通过使用`@RestController`注解,我们可以创建处理HTTP请求的控制器类,而`@RequestMapping`、`@GetMapping`、`@PostMapping`等注解则...