如何:从Spring 4.0快速入门以构建简单的REST-Like API(演练)

如何:从Spring 4.0快速入门以构建简单的REST-Like API(演练)

关于使用Spring MVC创建Web API的另一篇教程。 不太复杂。 只是一个演练。 生成的应用程序将提供简单的API,将Mongo作为其持久性,并将通过Spring Security进行保护。

入门– POM

当然,我仍然是Maven的忠实拥护者,因此该项目基于Maven。 既然有可用的Spring 4.0 RC2,我决定使用其新的依赖项管理,从而产生以下pom.xml:转到Spring MVC应用程序非常简单。 新的东西是dependencyManagement元素。 对此的更多说明可以在这里找到: http : //spring.io/blog/2013/12/03/spring-framework-4-0-rc2-available

组态

使用JavaConfig配置该应用程序。 我将其分为几个部分:

服务配置

@Configuration
public class ServicesConfig {@Autowiredprivate AccountRepository accountRepository;@Beanpublic UserService userService() {return new UserService(accountRepository);}@Beanpublic PasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance();}
}

没有组件扫描。 真的很简单。

持久性配置

具有所有可用存储库的MongoDB配置。 在这个简单的应用程序中,我们只有一个存储库,因此配置非常简单。

@Configuration
class PersistenceConfig {@Beanpublic AccountRepository accountRepository() throws UnknownHostException {return new MongoAccountRepository(mongoTemplate());}@Beanpublic MongoDbFactory mongoDbFactory() throws UnknownHostException {return new SimpleMongoDbFactory(new Mongo(), "r");}@Beanpublic MongoTemplate mongoTemplate() throws UnknownHostException {MongoTemplate template = new MongoTemplate(mongoDbFactory(), mongoConverter());return template;}@Beanpublic MongoTypeMapper mongoTypeMapper() {return new DefaultMongoTypeMapper(null);}@Beanpublic MongoMappingContext mongoMappingContext() {return new MongoMappingContext();}@Beanpublic MappingMongoConverter mongoConverter() throws UnknownHostException {MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), mongoMappingContext());converter.setTypeMapper(mongoTypeMapper());return converter;}
}

安全配置

从理论上讲,Spring Security 3.2可以使用JavaConfig进行完全配置。 对我来说,这仍然是一种理论,因此我在这里使用XML:

@Configuration
@ImportResource("classpath:spring-security-context.xml")
public class SecurityConfig {}

XML:如您所见,API将使用基本身份验证。

WebAppInitializer

我们不需要web.xml,因此我们使用以下代码来配置Web应用程序:

@Order(2)
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}@Overrideprotected Class[] getRootConfigClasses() {return new Class[] {ServicesConfig.class, PersistenceConfig.class, SecurityConfig.class};}@Overrideprotected Class[] getServletConfigClasses() {return new Class[] {WebMvcConfig.class};}@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();characterEncodingFilter.setEncoding("UTF-8");characterEncodingFilter.setForceEncoding(true);return new Filter[] {characterEncodingFilter};}@Overrideprotected void customizeRegistration(ServletRegistration.Dynamic registration) {        registration.setInitParameter("spring.profiles.active", "default");}
}

WebAppSecurityInitializer

Spring Security的新功能3。

@Order(1)
public class WebAppSecurityInitializer extends AbstractSecurityWebApplicationInitializer {}

WebMvcConfig

调度程序Servlet配置。 真的很基础。 只有关键组件才能构建简单的API。

@Configuration
@ComponentScan(basePackages = { "pl.codeleak.r" }, includeFilters = {@Filter(value = Controller.class)})
public class WebMvcConfig extends WebMvcConfigurationSupport {private static final String MESSAGE_SOURCE = "/WEB-INF/i18n/messages";@Overridepublic RequestMappingHandlerMapping requestMappingHandlerMapping() {RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();requestMappingHandlerMapping.setUseSuffixPatternMatch(false);requestMappingHandlerMapping.setUseTrailingSlashMatch(false);return requestMappingHandlerMapping;}@Bean(name = "messageSource")public MessageSource messageSource() {ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();messageSource.setBasename(MESSAGE_SOURCE);messageSource.setCacheSeconds(5);return messageSource;}@Overridepublic Validator getValidator() {LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();validator.setValidationMessageSource(messageSource());return validator;}@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}
}

这就是配置。 简单。

索引控制器

为了验证配置是否正确,我创建了一个IndexController,它提供简单的“ Hello,World”之类的文本:

@Controller
@RequestMapping("/")
public class IndexController {@RequestMapping@ResponseBodypublic String index() {return "This is an API endpoint.";}
}

运行应用程序时,您应该在浏览器中看到此文本。

构建API

用户服务

要完成Spring Security配置,实际上实际上仍然需要一部分:UserService哪个实例是先前创建的:

public class UserService implements UserDetailsService {private AccountRepository accountRepository;public UserService(AccountRepository accountRepository) {this.accountRepository = accountRepository;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {Account account = accountRepository.findByEmail(username);if(account == null) {throw new UsernameNotFoundException("user not found");}return createUser(account);}public void signin(Account account) {SecurityContextHolder.getContext().setAuthentication(authenticate(account));}private Authentication authenticate(Account account) {return new UsernamePasswordAuthenticationToken(createUser(account), null, Collections.singleton(createAuthority(account)));  }private User createUser(Account account) {return new User(account.getEmail(), account.getPassword(), Collections.singleton(createAuthority(account)));}private GrantedAuthority createAuthority(Account account) {return new SimpleGrantedAuthority(account.getRole());}}

要求是建立一个处理3种方法的API端点:获取当前登录的用户,获取所有用户(不是很安全),创建新帐户。 因此,让我们开始吧。

帐户

该帐户将是我们的第一个Mongo文档。 这真的很容易:

@SuppressWarnings("serial")
@Document
public class Account implements java.io.Serializable {@Idprivate String objectId;@Email@Indexed(unique = true)private String email;@JsonIgnore@NotBlankprivate String password;private String role = "ROLE_USER";private Account() {}public Account(String email, String password, String role) {this.email = email;this.password = password;this.role = role;}// getters and setters
}

资料库

我从界面开始:

public interface AccountRepository {Account save(Account account);List findAll();Account findByEmail(String email);
}

以及后来的Mongo实现:

public class MongoAccountRepository implements AccountRepository {private MongoTemplate mongoTemplate;public MongoAccountRepository(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}@Overridepublic Account save(Account account) {mongoTemplate.save(account);return account;}@Overridepublic List findAll() {return mongoTemplate.findAll(Account.class);}@Overridepublic Account findByEmail(String email) {return mongoTemplate.findOne(Query.query(Criteria.where("email").is(email)), Account.class);}
}

API控制器

所以我们快到了。 我们需要将内容提供给用户。 因此,让我们创建端点:

@Controller
@RequestMapping("api/account")
class AccountController {private AccountRepository accountRepository;@Autowiredpublic AccountController(AccountRepository accountRepository) {this.accountRepository = accountRepository;}@RequestMapping(value = "current", method = RequestMethod.GET)@ResponseStatus(value = HttpStatus.OK)@ResponseBody@PreAuthorize(value = "isAuthenticated()")public Account current(Principal principal) {Assert.notNull(principal);return accountRepository.findByEmail(principal.getName());}@RequestMapping(method = RequestMethod.GET)@ResponseStatus(value = HttpStatus.OK)@ResponseBody@PreAuthorize(value = "isAuthenticated()")public Accounts list() {List accounts = accountRepository.findAll();return new Accounts(accounts);}@RequestMapping(method = RequestMethod.POST)@ResponseStatus(value = HttpStatus.CREATED)@ResponseBody@PreAuthorize(value = "permitAll()")public Account create(@Valid Account account) {accountRepository.save(account);return account;}private class Accounts extends ArrayList {public Accounts(List accounts) {super(accounts);}}
}

希望您注意到我们直接与存储库进行通讯,因此不会对密码进行编码。 如果需要,可以稍后修复一些小细节。 现在可以了。

整理起来

我最后需要的是一些错误处理程序,以便使用者可以用JSON而不是HTML看到错误消息。 使用Spring MVC和@Controller建议,这很简单。

@ControllerAdvice
public class ErrorHandler {@ExceptionHandler(value = Exception.class)@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodypublic ErrorResponse errorResponse(Exception exception) {return new ErrorResponse(exception.getMessage());}}public class ErrorResponse {private String message;public ErrorResponse(String message) {this.message = message;}public String getMessage() {return message;}
}

如果您想在Spring 4中看到@ControllerAdvice的更多高级用法,请阅读
这个帖子 。

测试应用

作为一个单元测试极客,我应该首先创建单元测试。 但是……我只是想测试一个新工具:Postman(Chrome扩展程序)。 所以我做了:

获取帐户(未授权):

gna1

邮政帐户(不需要身份验证:

gna2

获取帐户(授权):

gna3

获取当前帐户(授权):

gna4

我们完了

现在就这样。 希望您喜欢我喜欢创建该项目。 这个项目和这篇文章总共花了我大约3个小时。 我大部分时间都花在弄清楚安全性配置上(我希望它完全使用Java)并编写此演练。

参考:操作方法:从我们的JCG合作伙伴 Rafal Borowiec在Codeleak.pl博客上快速开始于Spring 4.0,以构建一个简单的REST-Like API(演练) 。

翻译自: https://www.javacodegeeks.com/2013/12/how-to-get-started-quickly-with-spring-4-0-to-build-a-simple-rest-like-api-walkthrough.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01-Web客户端与服务器详解

1、CS与BS 软件使用方式上两种划分  C/S架构 Client/ServerPC客户端、服务器架构 特点:   在服务器当中就主要是一个数据库,把所有的业务逻辑以及界面都交给客户端完成 优点:   较为安全,用户界面丰富,用户体验好…

axi ps读写pl_PL读写DDR:Datamover能干什么

最近发现工程项目中一直在用AXI-DMA。这玩意儿搬数据倒是没问题,就是用axi-lite配置起来非常反人类。。。简单的办法其实是用datamover ip核。这个ip核能干嘛呢。准备写个文章解析一下。由于好多feature没用过,所以仅仅看文档可能理解有误,欢…

在10分钟内在新Mac中设置Java开发环境(更新)

这只是一个小的更新文章,它引用了2个较旧的条目( a , b ),我将它们合并为一个步骤,就像一步操作,并确保所有功能都在最新的MacOSX 10.9 Mavericks下工作 。 我主要针对的是初次尝试设置其环境的…

linux path 与 classpath 区别

linux path 与 classpath 区别 一、OS依据path中的路径信息来寻找可执行指令; 例如: cat /etc/profile 我们就可以在任意目录执行hadoop / hdfs / yarn / java 等相关命令了 export HADOOP_HOME/opt/hadoop/hadoop-2.6.0 export JAVA_HOME/home/jdk1.8.0…

开启9008端口进入深刷模式

除了前文所述,使用深刷线,还可以用命令开启9008端口,进入深刷模式。 adb reboot edl fastboot oem edl 这个在小米4c上测试ok 下面这个可能用于其他手机。 fastboot reboot emergency http://www.znsjw.net/nd.jsp?id19 小米绕BL锁9008工程…

hashmap为什么用红黑树_要看HashMap源码,先来看看它的设计思想

HashMap 是日常开发中,用的最多的集合类之一,也是面试中经常被问到的 Java 类之一。同时,HashMap 在实现方式上面又有十分典型的范例。不管是从哪一方面来看,学习 HashMap 都可以说是有利无害的。分析 HashMap 的源码的文章在网上…

实现CA和证书申请

文字说明 1 在CA上执行,建立CA cd /etc/pki/CA touch index.txt echo 0F > serial (umask 077;openssl genrsa -out private/cakey.pem 2048) openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650 填写多项内容:国家&#xff…

端口如何支持非localhost访问_新特性解读 | MySQL 8.0.19 支持 DNS SRV

转载自公众号:玩转MySQL作者:洪斌MySQL Router 是 InnoDB Cluster 架构的访问入口,在架构部署上,官方给出的建议是 router 与应用端绑定部署,避免 router 单点问题。之前还有客户咨询,能否 router 不与应用…

记录奥运-当今五大Java记录框架之间的竞赛

开发人员:Takipi会告诉您何时新代码在生产中中断– Log4J vs SLF4J简单vs Logback vs Java Util日志记录vs LOG4J2 日志记录实际上是每个服务器端应用程序中古老而固有的部分。 这是应用程序以持久且可读的方式输出实时状态的主要方法。 某些应用程序每天可能仅记录…

移动端实现元素拖拽效果插件_基于自然流布局的可视化拖拽搭建平台设计方案...

LowCode 是高效、高性能的拖拽式低代码开发平台. 也是笔者最近一直在研究的方向, 对于可视化搭建平台的实现方案笔者之前写过很多文章, 这里带大家探索一个新方向——基于自然流布局的可视化搭建平台.在我们之前实现的 h5-dooring 搭建平台中, 我们采用了网格布局的方式来实现拖…

07-数据类型

【转】07-数据类型 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考链接:http://www.runoob.com/mysql/mysql-data-types.html mysql常用数据类型概括&#x…

yii::$app-mongodb 查询纪录数_老詹总决赛有多强?12项数据领先乔丹科比,已握10项数据纪录...

勒布朗詹姆贡献了38分16个篮板和10个助攻的狂暴三双数据,并率领湖人淘汰了掘金,这使得他迈进了职业生涯第10次总决赛舞台。我们都知道,詹姆斯几乎统治着NBA季后赛大部分数据纪录,事实上,他在总决赛同样如此。根据《sta…

前端共享桌面_2020 前端学习路线总结,哎呦,不错哦!

2020 前端学习路线总结在 GitHub 看到一个很不错的前端学习路线图(roadmap),从前端基础到前端工程化,再到跨端,都有知识点的覆盖,非常推荐阅读。图下面是我翻译的一个文字版,可以先看图再看文字…

Confluence 6 高级性能诊断

请在你的系统服务请求中包括下面所有的信息,如果可能的话,你也可以在请求中包括你认为最有可能出现的问题。这样的话,可以避免我们进一步对你系统的问题进行询问。 系统信息 Confluence 服务器 你系统信息的屏幕截图 Confluences Administrat…

RequireJS使用注意地方

使用RequireJS做异步模块加载,有几点值得注意的地方: 1.模块定义两种写法 1. 存在依赖的函数式定义 如果模块存在依赖:则第一个参数是依赖的名称数组;第二个参数是函数,在模块的所有依赖加载完毕后,该函…

WildFly上具有AngularJS的Java EE 7和Java WebSocket API(JSR 356)

这篇博客文章描述了用于WebSocket协议的Java API(JSR 356) (这是Java EE 7平台的四个最新JSR之一),并提供了部署在WildFly 8上并可以在OpenShift上在线获得的具体应用程序。 [FR]版本的法语( HTML或PDF &a…

日期加减加1天_2小时整理了13个时间日期函数,动图演示简单易学,收藏备用吧...

Hello,大家好,今天跟大家整理汇总了13个工作中经常用到的日期与时间函数的使用方法,学会它们几乎可以解决所有工作中遇到的,关于日期与时间提取与转换的问题。话不多说,让我们直接开始吧一、了解时间与日期的本质工作中…

点云数据显示_vispy 显示 kitti 点云数据

国内博客找了一圈,居然没有发现有用 vispy 做可视化的代码,这里做一个简单的示例,代码大部分来自官方。import numpy as np import vispy.scene from vispy.scene import visuals import sys# Make a canvas and add simple view canvas vis…

Webpack 常用命令总结以及常用打包压缩方法

前言:Webpack是一款基于node的前端打包工具,它可以将很多静态文件打包起来,自动处理依赖关系后,生成一个.js文件,然后让html来引用,不仅可以做到按需加载,而且可以减少HTTP请求,节约…

CSS3 Filter详解(改变模糊度 亮度 透明度等方法)

文章目录 1.模糊2.灰度3.亮度4.对比度5.饱和度6.色相旋转7.反色8.阴影9.透明度10.褐色CSS3 Filter(滤镜)属性提供了提供模糊和改变元素颜色的功能。CSS3 Fitler 常用于调整图像的渲染、背景或边框显示效果。 -webkit-filter是css3的一个属性,…