www.how2j.com_HOW-TO:快速开始使用Spring 4.0,以构建简单的REST-Like API(演练)

www.how2j.com

HOW-TO:快速开始使用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

www.how2j.com

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

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

相关文章

flutter 返回指定界面_Flutter页面路由导航及传参

转载请注明出处: https://learnandfish.com/概述 每个应用都有很多个页面,在flutter中同样也有很多页面,被称之为路由(Router),页面之间的跳转通过导航器(Navigator)进行管理。其中 Navigator.push 和 Navigator.pop 是最简单的跳转到新页面和…

正确的工作流程:我应该使用哪个OAuth 2.0流程?

什么是OAuth 2.0 OAuth 2.0是一个已被广泛采用的委托授权框架,已经存在了很多年,并且似乎已经存在。 如果您不熟悉OAuth 2.0的基本概念,可以使用 川崎孝彦写的优秀文章 。 这只是OAuth 2.0各方的简要提醒: 资源所有者–受保护资…

mysql workbench入门_5分钟入门MySQL Workbench

接下来进入下一步,使用Workbench执行sql文件:1.打开Workbench,主页面上点击要connect的连接。2.注意系统偏好设置里,MySQL是running的状态,否则无法执行。创建数据库:点击创建数据库按钮,输入数…

使用Spring Boot和Vue进行有益的开发

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。 Vue是一个Web框架,由于它的精简和刻薄,最近引起了很多关注。 …

mysql mydumper_系统运维|Mydumper-MySQL数据库备份工具

Mydumper 是 MySQL 数据库服务器备份工具,它比 MySQL 自带的 mysqldump 快很多。它还有在转储的同时获取远程服务器二进制日志文件的能力。Mydumper 的优势并行能力 (因此有高速度) 和性能 (高效的代码避免了耗费 CPU 处理能力的字符集转换过程)更容易管理输出 (每个…

vue调用手机相机相册_详解Vue调用手机相机和相册以及上传

组件选中{{imgList.length}}张文件,共{{bytesToSize(this.size)}}javaScript代码export default {name: "cameras-and-albums",data(){return{imgList: [],datas: new FormData(),files:0,size:0}},methods:{//调用相册&相机fileClick() {$(#upload_f…

红旗linux mysql_恢复 - 红旗Linux案例精选:Amanda集中备份实例详细讲解_数据库技术_Linux公社-Linux系统门户网站...

五、恢复假定我们需要恢复cp3上一些丢失的数据,首先用amandabackup帐号登录cp2机器,创建/etc/amanda/amanda-client.conf文件,内容如下:## amanda.conf - sample Amanda client configuration file.## This file normally goes in…

linuxpip安装python包_Windows+Linux安装Python包管理工具pip

WindowsLinux安装Python包管理工具pipWindows安装Python包管理工具pippip是一个Python包管理工具,主要是用于安装PyPI上的软件包,可以替代easy_install工具。一、前期准备首先确认windows机器上面是否已经安装好了python。在cmd中输入python --version和…

mysql 深胡_Mysql胡说八道

mysql索引今天看了一些关于MySQL相关的东西,来做一些碎碎念,写这些可能只是觉得自己看东西老爱忘23333.先来看一组MySQL数据,如图我们要查看最后id11的数据,如果我们不加索引的话会怎样呢?他会一条一条的比对&#xff…

java public main_实例分析Java中public static void main(String args[])是什么意思

本文实例讲述了Java中public static void main(String args[])的来龙去脉。分享给大家供大家参考,具体如下:public static void main(String[] args)这绝对不是凭空想出来的,也不是没有道理的死规定,而是java程序执行的需要。jvm在…

java浏览文件夹_一个用java实现简单的文件浏览器

[java]代码库import java.awt.*;import java.awt.event.*;import java.net.URL;import javax.swing.*;//文件浏览器public class HTTPBrowserDemo extends JFrame {private static final long serialVersionUID -5794029080886644211L;JTextField jtfAddress; // 输入文件地址…

java奥运会安排赛程问题_记录奥运-当今五大Java记录框架之间的竞赛

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

为什么在子类中不重写超类的实例变量

当我们在父类和子类中创建一个具有相同名称的变量,并尝试使用持有子类对象的父类引用访问它时,我们会得到什么? 为了理解这一点,让我们考虑下面的示例,其中在Parent和Child类中声明一个具有相同名称的变量x 。 class…

cocos lua调用java_【Tech-Lua】Cocos-2dx-Lua调用java的小白教程(三)

上周五下班前,打包成功了。我很高兴,周六去踢场足球,周日去现场看了最后一分钟掉球的恒大,度过了一个愉快的周末。然后,噩梦的周一开始了。我再次打包,打算打包就安装,但结果是失败的。为何&…

github上java项目_GitHub上10,000个最受欢迎的Java项目-以下是他们使用的顶级库

github上java项目随着Java开发人员使用既成熟又高度发展的语言来工作,无论何时编写新代码,我们都将面临一个持续的困境–使用大家都在谈论的热门新技术,或者坚持使用久经考验的库? 由于Java应用程序的很大一部分是商业性质的&…

char java 回文_LeetCode刷题笔记(Java)---第1-18题

题目来自LeetCode文章目录全部章节1-18题19-40题41-60题61-80题81-100题101-120题121-140题1.两数之和2.两数相加3.无重复字符串的最长子串4.寻找两个有序数组的中位数5.最长回文子串6.Z 字形变换7.整数反转8.字符串转换整数 (atoi)9.回文数10.正则表达式匹配11.盛最多水的容器…

使用PostgreSQL使用Spring Boot和JPA构建基本应用

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。 每个不平凡的应用程序都需要一种保存和更新数据的方法:可通过HTTP访问的资…

通过示例了解Apache Ignite Baseline拓扑

点燃基准拓扑或BLT表示群集中的一组服务器节点,这些服务器节点将数据持久存储在磁盘上。 其中,N1-2和N5服务器节点是具有本机持久性的Ignite集群的成员,这些集群使数据能够持久存储在磁盘上。 N3-4和N6服务器节点是Ignite群集的成员&#x…

Spring Boot集成测试中@ContextConfiguration和@SpringApplicationConfiguration之间的区别

即使同时使用ContextConfiguration和SpringApplicationConfiguration批注以及SpringJUnit4ClassRunner来指定如何加载Spring应用程序上下文,它们之间也存在细微的差异。 尽管ContextConfiguration在加载应用程序上下文方面表现出色,但没有充分利用Spring…

vert.x_使用vert.x 2.0,RxJava和mongoDB创建simpe RESTful服务

vert.x中断了将近半年后发表了一篇新文章。 在本文中,我们将快速了解如何开始使用vert.x,更有趣的是,如何使用RxJava简化异步系统的编程。 我们将涵盖以下主题: 使用Maven创建一个空的vert.x项目 导入IntelliJ并创建一个简单的H…