spring rest| 耗时:0.463秒|12495条结果

Spring REST

前面介绍过Spring的MVC结合不同的view显示不同的数据,如:结合json的view显示json、结合xml的view显示xml文档。那么这些数据除了在WebBrowser中用JavaScript来调用以外,还可以用远程服务器的Java程序、C#程序来调用。也就是说现在的程序不仅在BS中能
http://www.itnose.net/detail/474869.html 2014-01-22 18:31   [Spring]

Spring REST

前面介绍过Spring的MVC结合不同的view显示不同的数据,如:结合json的view显示json、结合xml的view显示xml文档。那么这些数据除了在WebBrowser中用JavaScript来调用以外,还可以用远程服务器的Java程序、C#程序来调用。也就是说现在的程序不仅在BS中能
http://www.itnose.net/detail/474754.html 2014-01-22 18:30   [Spring]

Spring REST 异常处理

在上一篇中写到了Spring MVC的异常处理,SpringMVC捕获到异常之后会转到相应的错误页面,但是我们REST API ,一般只返回结果和状态码,比如发生异常,只向客户端返回一个500的状态码,和一个错误消息。如果我们不做处理,客户端通过REST API访问,发生异常的话,会得到一个错误
http://www.itnose.net/detail/6300057.html 2015-06-19 04:22   [J2SE]

使用 Spring HATEOAS 开发 REST 服务

绝大多数开发人员对于 REST 这个词都并不陌生。自从 2000 年 Roy Fielding 在其博士论文中创造出来这个词之后,REST 架构风格就很快地流行起来,已经成为了构建 Web 服务时应该遵循的事实标准。很多 Web 服务和 API 都宣称满足了 REST 架构风格的要求,即所谓的“RESTful”服务。不过就如同其他很多流行的概念一样,不少人对于 REST 的含义还是存在或多或少的种种误解。REST 在某些时候被当成了一种营销的手段。不少所谓的“RESTful” Web 服务或 API 实际上并不满足 REST 架构风格的要求。这其中的部分原因在于 REST 的含义比较复杂,包含很多不同方面的内容。本文首先对 REST 架构做一个简单的说明以澄清某些误解。 REST 架构 REST 是 Representational state transfer 的缩写,翻译过来的意思是表达性状态转换。REST 是一种架构风格,它包含了一个分布式超文本系统中对于组件、连接器和数据的约束。REST 是作为互联网自身架构的抽象而出现的,其关键在于所定义的架构上的各种约束。只有满足这些约束,才能称之为符合 REST 架构风格。REST 的约束包括: 客户端-服务器结构。通过一个统一的接口来分开客户端和服务器,使得两者可以独立开发和演化。客户端的实现可以简化,而服务器可以更容易的满足可伸缩性的要求。 无状态。在不同的客户端请求之间,服务器并不保存客户端相关的上下文状态信息。任何客户端发出的每个请求都包含了服务器处理该请求所需的全部信息。 可缓存。客户端可以缓存服务器返回的响应结果。服务器可以定义响应结果的缓存设置。 分层的系统。在分层的系统中,可能有中间服务器来处理安全策略和缓存等相关问题,以提高系统的可伸缩性。客户端并不需要了解中间的这些层次的细节。 按需代码(可选)。服务器可以通过传输可执行代码的方式来扩展或自定义客户端的行为。这是一个可选的约束。 统一接口。该约束是 REST 服务的基础,是客户端和服务器之间的桥梁。该约束又包含下面 4 个子约束。 资源标识符。每个资源都有各自的标识符。客户端在请求时需要指定该标识符。在 REST 服务中,该标识符通常是 URI。客户端所获取的是资源的表达(representation),通常使用 XML 或 JSON 格式。 通过资源的表达来操纵资源。客户端根据所得到的资源的表达中包含的信息来了解如何操纵资源,比如对资源进行修改或删除。 自描述的消息。每条消息都包含足够的信息来描述如何处理该消息。 超媒体作为应用状态的引擎(HATEOAS)。客户端通过服务器提供的超媒体内容中动态提供的动作来进行状态转换。这也是本文所要介绍的内容。 在了解 REST 的这些约束之后,就可以对“表达性状态转换”的含义有更加清晰的了解。“表达性”的含义是指对于资源的操纵都是通过服务器提供的资源的表达来进行的。客户端在根据资源的标识符获取到资源的表达之后,从资源的表达中可以发现其可以使用的动作。使用这些动作会发出新的请求,从而触发状态转换。 HATEOAS 约束 HATEOAS(Hypermedia as the engine of application state)是 REST 架构风格中最复杂的约束,也是构建成熟 REST 服务的核心。它的重要性在于打破了客户端和服务器之间严格的契约,使得客户端可以更加智能和自适应,而 REST 服务本身的演化和更新也变得更加容易。 在介绍 HATEOAS 之前,先介绍一下 Richardson 提出的 REST 成熟度模型。该模型把 REST 服务按照成熟度划分成 4 个层次: 第一个层次(Level 0)的 Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形式。SOAP 和 XML-RPC 都属于此类。 第二个层次(Level 1)的 Web 服务引入了资源的概念。每个资源有对应的标识符和表达。 第三个层次(Level 2)的 Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用 HTTP 状态码来表示不同的结果。如 HTTP GET 方法来获取资源,HTTP DELETE 方法来删除资源。 第四个层次(Level 3)的 Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。 从上述 REST 成熟度模型中可以看到,使用 HATEOAS 的 REST 服务是成熟度最高的,也是推荐的做法。对于不使用 HATEOAS 的 REST 服务,客户端和服务器的实现之间是紧密耦合的。客户端需要根据服务器提供的相关文档来了解所暴露的资源和对应的操作。当服务器发生了变化时,如修改了资源的 URI,客户端也需要进行相应的修改。而使用 HATEOAS 的 REST 服务中,客户端可以通过服务器提供的资源的表达来智能地发现可以执行的操作。当服务器发生了变化时,客户端并不需要做出修改,因为资源的 URI 和其他信息都是动态发现的。 回页首 示例 本文将通过一个完整的示例来说明 HATEOAS。该示例是一个常见的待办事项的服务,用户可以创建新的待办事项、进行编辑或标记为已完成。该示例中包含的资源如下: 用户:应用中的用户。 列表:待办事项的列表,属于某个用户。 事项:具体的待办事项,属于某个列表。 应用提供相关的 REST 服务来完成对于列表和事项两个资源的 CRUD 操作。 回页首 Spring HATEOAS 如果 Web 应用基于 Spring 框架开发,那么可以直接使用 Spring 框架的子项目 HATEOAS 来开发满足 HATEOAS 约束的 Web 服务。本文的示例应用基于 Java 8 和使用 Spring Boot 1.1.9 来创建,Spring HATEOAS 的版本是 0.16.0.RELEASE。 基本配置 满足 HATEOAS 约束的 REST 服务最大的特点在于服务器提供给客户端的表达中包含了动态的链接信息,客户端通过这些链接来发现可以触发状态转换的动作。Spring HATEOAS 的主要功能在于提供了简单的机制来创建这些链接,并与 Spring MVC 框架有很好的集成。对于已有的 Spring MVC 应用,只需要一些简单的改动就可以满足 HATEOAS 约束。对于一个 Maven 项目来说,只需要添加代码清单 1中的依赖即可。 清单 1. Spring HATEOAS 的 Maven 依赖声明 <dependency>   <groupId>org.springframework.hateoas</groupId>   <artifactId>spring-hateoas</artifactId>   <version>0.16.0.RELEASE</version> </dependency> 资源 REST 架构中的核心概念之一是资源。服务器提供的是资源的表达,通常使用 JSON 或 XML 格式。在一般的 Web 应用中,服务器端代码会对所使用的资源建模,提供相应的模型层 Java 类,这些模型层 Java 类通常包含 JPA 相关的注解来完成持久化。在客户端请求时,服务器端代码通过 Jackson 或 JAXB 把模型对象转换成 JSON 或 XML 格式。代码清单 2给出了示例应用中表示列表的模型类 List 的声明。 清单 2. 表示列表的模型类 List 的声明 @Entity public class List extends AbstractEntity {    private String name;    @ManyToOne    @JsonIgnore    private User user;    @OneToMany(mappedBy = "list", fetch = FetchType.LAZY)    @JsonIgnore    private Set<Item> items = new HashSet<>();    protected List() {    }    public List(String name, User user) {        this.name = name;        this.user = user;    }    public String getName() {        return name;    }    public User getUser() {        return user;    }    public Set<Item> getItems() {        return items;    } } 当客户端请求某个具体的 List 类的对象时,服务器端返回如代码清单 3所示的 JSON 格式的表达。 清单 3. List 类的对象的 JSON 格式的表达 {    "id": 1,    "name": "Default" } 在代码清单 3中,服务器端返回的只是模型类对象本身的内容,并没有提供相关的链接信息。为了把模型对象类转换成满足 HATEOAS 要求的资源,需要添加链接信息。Spring HATEOAS 使用 org.springframework.hateoas.Link 类来表示链接。Link 类遵循 Atom 规范中对于链接的定义,包含 rel 和 href 两个属性。属性 rel 表示的是链接所表示的关系(relationship),href 表示的是链接指向的资源标识符,一般是 URI。资源通常都包含一个属性 rel 值为 self 的链接,用来指向该资源本身。 在创建资源类时,可以继承自 Spring HATEOAS 提供的 org.springframework.hateoas.Resource 类,Resource 类提供了简单的方式来创建链接。代码清单 4给出了与模型类 List 对应的资源类 ListResource 的声明。 清单 4. 模型类 List 对应的资源类 ListResource 的声明 public class ListResource extends Resource {    private final List list;    public ListResource(List list) {        super(list);        this.list = list;        add(new Link("http://localhost:8080/lists/1"));        add(new Link("http://localhost:8080/lists/1/items", "items"));    }    public List getList() {        return list;    } } 如代码清单 4所示,ListResource 类继承自 Resource 类并对 List 类的对象进行了封装,添加了两个链接。在使用 ListResource 类之后,服务器端返回的表达格式如代码清单 5所示。 清单 5. 使用 ListResource 类之后的 JSON 格式的表达 {    "list": {        "id": 1,        "name": "Default"    },    "links": [        {            "rel": "self",            "href": "http://localhost:8080/lists/1"        },        {            "rel": "items",            "href": "http://localhost:8080/lists/1/items"        }    ] } 代码清单 5的 JSON 内容中添加了额外的 links 属性,并包含了两个链接。不过模型类对象的内容被封装在属性 list 中。这是因为 ListResource 类直接封装了整个的 List 类的对象,而不是把 List 类的属性提取到 ListResource 类中。如果需要改变输出的 JSON 表达的格式,可以使用另外一种封装方式的 ListResource 类,如代码清单 6所示。 清单 6. 不同封装格式的 ListResource 类 public class ListResource extends Resource {    private final Long id;       private final String name;    public ListResource(List list) {        super(list);        this.id = list.getId();        this.name = list.getName();        add(new Link("http://localhost:8080/lists/1"));        add(new Link("http://localhost:8080/lists/1/items", "items"));    }    public Long getId() {      
http://www.itnose.net/detail/6378883.html 2015-09-27 23:48   [Spring]

spring mvc rest风格接口

我现在用spring mvc 加上portlet组件 做的一个项目,现在要求我把之前的写好的一个对文件加密的方法改成 rest风格的接口,供别人调用  ,项目里边的框架都搭好了,不用再配置其它任何东西了,应该是只改方法就行.下面是我的方法 public  void  encryptFile(String file,String destFile,Key key) throws Exception{ key=(new EncryptionUtil(uuidKey()).getKey()); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE,key); //判断密钥状态 if(getKeyState(uuidKey())==1){ InputStream is =new FileInputStream(file);  OutputStream os = new FileOutputStream(destFile); CipherInputStream cis = new CipherInputStream(is, cipher); byte [] buffer = new byte [1024];   int r;     while ((r = cis.read(buffer)) > 0) {        os.write(buffer, 0, r);        }        cis.close();            os.close();        is.close();   }else{ System.out.println("------密钥已过期-----"); } } 怎么改?求讲解或代码,在线等 回复讨论(解决方案) 做个页面让别人上传文件 和 key 处理完成后把新文件让他下载 你是要改什么?不知道如何做rest,还是? @Path("encryptRest") @Component @Scope("request") public class encryptResource { @POST @Path("/encry") @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public  String  encryptFile( @PathParam("file")String file, @PathParam("destFile")String destFile,Key key) throws Exception { String Success = "Encryption of success"; String Failure = "Key has expired"; key=(new EncryptionUtil(uuidKey()).getKey()); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE,key); //判断密钥状态 if(getKeyState(uuidKey())==1){ InputStream is =new FileInputStream(file);  OutputStream os = new FileOutputStream(destFile); CipherInputStream cis = new CipherInputStream(is, cipher); byte [] buffer = new byte [1024];   int r; while ((r = cis.read(buffer)) > 0) {   os.write(buffer, 0, r);    }    cis.close();    os.close();    is.close();   return Success; }else{ System.out.println("------密钥已过期-----"); return Failure; } } }
http://www.itnose.net/detail/6113019.html 2014-09-16 20:05   [JavaWeb]

Spring MVC7.REST风格 CRUD

这样的问题: 优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀 若将DispatcherServlet 请求映射配置为 /, 则 Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求,SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误。 (2)解决方法: 在 SpringMVC 的配置文件中配置<mvc:default-servlet-handler/> <!-- 解决静态资源 将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler, 它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求, 就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求, 才由DispatcherServlet 继续处理 一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的WEB 服务器 的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定 --> <mvc:default-servlet-handler/> <mvc:annotation-driven></mvc:annotation-driven> 3.数据转换 (1)数据绑定流程 (2)内置转换 (3)自定义类型转换器—了解 ConversionService是 Spring 类型转换体系的核心接口。 可以利用 ConversionServiceFactoryBean在 Spring 的IOC容器中定义一个ConversionService. Spring 将自动识别出IOC 容器中的 ConversionService,并在 Bean 属性配置及SpringMVC 处理方法入参绑定等场合使用它进行数据的转换 可通过 ConversionServiceFactoryBean的 converters 属性注册自定义的类型转换器 <form action="testConversionServiceConverer" method="POST"> <!-- lastname-email-gender-department.id例如: GG-gg@qq.com-0-105--> 自定义转换器:Employee: <input type="text"name="employee"/> <input type="submit"value="Submit"/> </form> @Controller public class SpringMVCTest { @Autowired private EmployeeDao employeeDao; @RequestMapping("/testConversionServiceConverer") public String testConverter(@RequestParam("employee") Employee employee){ System.out.println("save" + employee); employeeDao.save(employee); return "redirect:/emps"; } } Spring定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactroyBean 中: Converter<S,T>:将 S 类型对象转为 T 类型对象 ConverterFactory:将相同系列多个 “同质” Converter封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将String 转换为Number 及Number 子类 (Integer、Long、Double 等)对象)可使用该转换器工厂类 GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换 /** * 自定义类型转换器 * @author Administrator * */ @Component public class EmployeeConverter implements Converter<String,Employee>{ @Override public Employee convert(String source) { if(source != null){ String [] vals = source.split("-"); //GG-gg@qq.com-0-105 if(vals != null && vals.length == 4){ String lastName = vals[0]; String email = vals[1]; Integer gender = Integer.parseInt(vals[2]); Department department = new Department(); department.setId(Integer.parseInt(vals[3])); Employee employee = new Employee(null, lastName,email, gender, department); System.out.println(source + "--convert--" + employee); return employee; } } return null; } } <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven> <!-- 配置 ConversionService --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <ref bean="employeeConverter"/> </set> </property> </bean> (4) 关于 mvc:annotation-driven <mvc:annotation-driven /> 会自动注册 RequestMappingHandlerMapping 、 RequestMappingHandlerAdapter 与 ExceptionHandlerExceptionResolver 三个bean。 还将提供以下支持: 支持使用 ConversionService 实例对表单参数进行类型转换 支持使用 @NumberFormatannotation 、 @DateTimeFormat 注解完成数据类型的格式化 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证 支持使用 @RequestBody 和 @ResponseBody 注解 (5) @InitBinder 由 @InitBinder 标识的方法 • , 可以 对 WebDataBinder 对 象 进 行初始化 。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定     @InitBinder 方法不能有返回 值 ,它必须声明为void• 。     @InitBinder 方法的参数通常是是 WebDataBinder 4. 数据格式化 首先创建: <mvc:annotation-driven/> < mvc:annotation-driven ></ mvc:annotation-driven > (1) 日期格式化 (2)数值格式化 5.数据检验 (1) JSR 303 JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 . JSR 303 通过 在 Bean 属性上 标 注 类似于 @NotNull
http://www.itnose.net/detail/6718733.html 2017-02-16 13:22   [Spring]

spring mvc和rest风格小例子

之前在新一个项目中用了spring3 的mvc开发,用得很爽,不过当时想找些入门的小例子时,找了好久也没找到, 现在写个简单的小例子出来给初学者学习下。 srping3也支持rest,所以例子也包括这部分内容。 先看web.xml配置 <!-- 像js,css,gif等静态文件,需要配置为
http://www.itnose.net/detail/6648873.html 2016-09-30 15:04   [Spring]

构建spring web mvc REST风格HelloWorld

void main(String[] args) { // SpringApplication.run(UserController.class); //} } 运行   第一种方式 通过在UserController中加上@EnableAutoConfiguration开启自动配置,然后通过SpringApplication.run(UserController.class);运行这个控制器;这种方式只运行一个控制器比较方便; 第二种方式 通过@Configuration+@ComponentScan开启注解扫描并自动注册相应的注解Bean package com.sishuok; import com.sishuok.controller.UserController; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * <p>User: Zhang Kaitao * <p>Date: 13-12-22 * <p>Version: 1.0 */ @Configuration @ComponentScan @EnableAutoConfiguration public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } } 到此,一个基本的REST风格的web应用就构建完成了。 地址栏输入http://localhost:8080/user/1即可看到json结果。 如果大家查看其依赖,会发现自动添加了需要相应的依赖(不管你用/不用),但是开发一个应用确实变得非常快速,对于想学习/体验Spring的新手,快速建立项目模型等可以考虑用这种方式。当然如果不想依赖这么多的jar包,可以去掉parent,然后自己添加依赖。 
http://www.itnose.net/detail/6641450.html 2016-09-11 21:12   [Spring]

Spring MVC Rest 返回值为空

;参考 Spring MVC Rest 学习 一:     参考Spring MVC Rest 学习 二:     对于Controller的接口,一开始如下声明:     
http://www.itnose.net/detail/6225061.html 2015-03-16 11:10   [Spring]

Creating a REST API with Spring Boot

Spring Boot is an opinionated framework that simplifies the development of Spring applications. It frees us from the slavery of complex configuration files and helps us to create standalone Spring applications that don’t need an external servlet container.This sounds almost too good to be true, but Spring Boot can really do all this.This blog post demonstrates how easy it is to implement a REST API that provides CRUD operations for todo entries that are saved to MongoDB database.Let’s start by creating our Maven project.Note: This blog post assumes that you have already installed the MongoDB database. If you haven’t done this, you can follow the instructions given in the blog post titled: Accessing Data with MongoDB. Creating Our Maven Project We can create our Maven project by following these steps: Use the spring-boot-starter-parent POM as the parent POM of our Maven project. This ensures that our project inherits sensible default settings from Spring Boot. Add the Spring Boot Maven Plugin to our project. This plugin allows us to package our application into an executable jar file, package it into a war archive, and run the application. Configure the dependencies of our project. We need to configure the following dependencies: The spring-boot-starter-web dependency provides the dependencies of a web application. The spring-data-mongodb dependency provides integration with the MongoDB document database. Enable the Java 8 Support of Spring Boot. Configure the main class of our application. This class is responsible of configuring and starting our application. The relevant part of our pom.xml file looks as follows:       <properties>     <!-- Enable Java 8 -->     <java.version>1.8</java.version>     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>     <!-- Configure the main class of our Spring Boot application -->     <start-class>com.javaadvent.bootrest.TodoAppConfig</start-class></properties>         <!-- Inherit defaults from Spring Boot --><parent>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-parent</artifactId>     <version>1.1.9.RELEASE</version></parent><dependencies>     <!-- Get the dependencies of a web application -->     <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-web</artifactId>     </dependency>     <!-- Spring Data MongoDB-->     <dependency>         <groupId>org.springframework.data</groupId>         <artifactId>spring-data-mongodb</artifactId>     </dependency></dependencies><build>     <plugins>         <!-- Spring Boot Maven Support -->         <plugin>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-maven-plugin</artifactId>         </plugin>     </plugins></build> Additional Reading: Spring Boot Reference Manual: 9.1.1 Maven installation Spring Boot Reference Manual: 12.1 Maven Spring Boot Maven Plugin - Usage Let’s move on and find out how we can configure our application. Configuring Our Application We can configure our Spring Boot application by following these steps: Create a TodoAppConfig class to the com.javaadvent.bootrest package. Enable Spring Boot auto-configuration. Configure the Spring container to scan components found from the child packages of the com.javaadvent.bootrest package. Add the main() method to the TodoAppConfig class and implement by running our application. The source code of the TodoAppConfig class looks as follows:       package com.javaadvent.bootrest;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@EnableAutoConfiguration@ComponentScanpublic class TodoAppConfig {          public static void main(String[] args) {         SpringApplication.run(TodoAppConfig.class, args);     }} We have now created the configuration class that configures and runs our Spring Boot application. Because the MongoDB jars are found from the classpath, Spring Boot configures the MongoDB connection by using its default settings.Additional Reading: Spring Boot Reference Manual: 13.2 Location the main application class Spring Boot Reference Manual: 14. Configuration classes The Javadoc of the @EnableAutoConfiguration annotation Spring Boot Reference Manual: 15. Auto-configuration The Javadoc of the SpringApplication class Spring Boot Reference Manual: 27.2.1 Connecting to a MongoDB database Let’s move on and implement our REST API. Implementing Our REST API We need implement a REST API that provides CRUD operations for todo entries. The requirements of our REST API are: A POST request send to the url ‘/api/todo’ must create a new todo entry by using the information found from the request body and return the information of the created todo entry. A DELETE request send to the url ‘/api/todo/{id}’ must delete the todo entry whose id is found from the url and return the information of the deleted todo entry. A GET request send to the url ‘/api/todo’ must return all todo entries that are found from the database. A GET request send to the url ‘/api/todo/{id}’ must return the information of the todo entry whose id is found from the url. A PUT request send to the url ‘/api/todo/{id}’ must update the information of an existing todo entry by using the information found from the request body and return the information of the updated todo entry. We can fulfill these requirements by following these steps: Create the entity that contains the information of a single todo entry. Create the repository that is used to save todo entries to MongoDB database and find todo entries from it. Create the service layer that is responsible of mapping DTOs into domain objects and vice versa. The purpose of our service layer is to isolate our domain model from the web layer. Create the controller class that processes HTTP requests and returns the correct response back to the client. Note: This example is so simple that we could just inject our repository to our controller. However, because this is not a viable strategy when we are implementing real-life applications, we will add a service layer between the web and repository layers.Let’s get started. Creating the Entity We need to create the entity class that contains the information of a single todo entry. We can do this by following these steps: Add the id, description, and title fields to the created entity class. Configure the id field of the entity by annotating the id field with the @Id annotation. Specify the constants (MAX_LENGTH_DESCRIPTION and MAX_LENGTH_TITLE) that specify the maximum length of the description and title fields. Add a static builder class to the entity class. This class is used to create new Todo objects. Add an update() method to the entity class. This method simply updates the title and description of the entity if valid values are given as method parameters. The source code of the Todo class looks as follows:       import org.springframework.data.annotation.Id;import static com.javaadvent.bootrest.util.PreCondition.isTrue;import static com.javaadvent.bootrest.util.PreCondition.notEmpty;import static com.javaadvent.bootrest.util.PreCondition.notNull;final class Todo {     static final int MAX_LENGTH_DESCRIPTION = 500;     static final int MAX_LENGTH_TITLE = 100;     @Id     private String id;     private String description;     private String title;     public Todo() {}     private Todo(Builder builder) {         this.description = builder.description;         this.title = builder.title;     }     static Builder getBuilder() {         return new Builder();     }     //Other getters are omitted     public void update(String title, String description) {         checkTitleAndDescription(title, description);         this.title = title;         this.description = description;     }     /**      * We don't have to use the builder pattern here because the constructed    * class has only two String fields. However, I use the builder pattern    * in this example because it makes the code a bit easier to read.      */     static class Builder {         private String description;         private String title;         private Builder() {}         Builder description(String description) {             this.description = description;             return this;         }         Builder title(String title) {             this.title = title;             return this;         }         Todo build() {             Todo build = new Todo(this);             build.checkTitleAndDescription(build.getTitle(), build.getDescription());             return build;         }     }     private void checkTitleAndDescription(String title, String description) {         notNull(title, "Title cannot be null");         notEmpty(title, "Title cannot be empty");         isTrue(title.length() <= MAX_LENGTH_TITLE,                 "Title cannot be longer than %d characters",                 MAX_LENGTH_TITLE        );         if (description != null) {             isTrue(description.length() <= MAX_LENGTH_DESCRIPTION,                     "Description cannot be longer than %d characters",                     MAX_LENGTH_DESCRIPTION            );         }     }} Additional Reading: Item 2: Consider a builder when faced with many constructor parameters Let's move on and create the repository that communicates with the MongoDB database. Creating the Repository We have to create the repository interface that is used to save Todo objects to MondoDB database and retrieve Todo objects from it.If we don’t want to use the Java 8 support of Spring Data, we could create our repository by creating an interface that extends the CrudRepository<T, ID> interface. However, because we want to use the Java 8 support, we have to follow these steps: Create an interface that extends the Repository<T, ID> interface. Add the following repository methods to the created interface: The void delete(Todo deleted) method deletes the todo entry that is given as a method parameter. The List<Todo> findAll() method returns all todo entries that are found from the database. The Optional<Todo> findOne(String id) method returns the information of a single todo entry. If no todo entry is found, this method returns an empty Optional. The Todo save(Todo saved) method saves a new todo entry to the database and returns the the saved todo entry. The source code of the TodoRepository interface looks as follows:       import org.springframework.data.repository.Repository;import java.util.List;import java.util.Optional;interface TodoRepository extends Repository<Todo, String> {     void delete(Todo deleted);     List<Todo> findAll();     Optional<Todo> findOne(String id);     Todo save(Todo saved);} Additional Reading: The Javadoc of the CrudRepository<T, ID> interface The Javadoc of the Repository<T, ID> interface Spring Data MongoDB Reference Manual: 5. Working with Spring Data Repositories Spring Data MongoDB Reference Manual: 5.3.1 Fine-tuning repository definition Let’s move on and create the service layer of our example application. Creating the Service Layer First, we have to create a service interface that provides CRUD operations for todo entries. The source code of the TodoService interface looks as follows:       import java.util.List;interface TodoService {     TodoDTO create(TodoDTO todo);     TodoDTO delete(String id);     List<TodoDTO> findAll();     TodoDTO findById(String id);     TodoDTO update(TodoDTO todo);} The TodoDTO class is a DTO that contains the information of a single todo entry. We will talk more about it when we create the web layer of our example application.Second, we have to implement the TodoService interface. We can do this by following these steps: Inject our repository to the service class by using constructor injection. Add a private Todo findTodoById(String id) method to the service class and implement it by either returning the found Todo object or throwing the TodoNotFoundException. Add a private TodoDTO convertToDTO(Todo model) method the service class and implement it by converting the Todo object into a TodoDTO object and returning the created object. Add a private List<TodoDTO> convertToDTOs(List<Todo> models) and implement it by converting the list of Todo objects into a list of TodoDTO objects and returning the created list. Implement the TodoDTO create(TodoDTO todo) method. This method creates a new Todo object, saves the created object to the MongoDB database, and returns the information of the created todo entry. Implement the TodoDTO delete(String id) method. This method finds the deleted Todo object, deletes it, and returns the information of the deleted todo entry. If no Todo object is found with the given id, this method throws the TodoNotFoundException. Implement the List<TodoDTO> findAll() method. This methods retrieves all Todo objects from the database, transforms them into a list of TodoDTO objects, and returns the created list. Implement the TodoDTO findById(String id) method. This method finds the Todo object from the database, converts it into a TodoDTO object, and returns the created TodoDTO object. If no todo entry is found, this method throws the TodoNotFoundException. Implement the TodoDTO update(TodoDTO todo) method. This method finds the updated Todo object from the database, updates its title and description, saves it, and returns the updated information. If the updated Todo object is not found, this method throws the TodoNotFoundException. The source code of the MongoDBTodoService looks as follows:       import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;import java.util.Optional;import static java.util.stream.Collectors.toList;@Servicefinal class MongoDBTodoService implements TodoService {     private final TodoRepository repository;     @Autowired     MongoDBTodoService(TodoRepository repository) {         this.repository = repository;     }     @Override     public TodoDTO create(TodoDTO todo) {         Todo persisted = Todo.getBuilder()                 .title(todo.getTitle())                 .description(todo.getDescription())                 .build();         persisted = repository.save(persisted);         return convertToDTO(persisted);     }     @Override     public TodoDTO delete(String id) {         Todo deleted = findTodoById(id);         repository.delete(deleted);         return convertToDTO(deleted);     }     @Override     public List findAll() {         List todoEntries = repository.findAll();         return convertToDTOs(todoEntries);     }     private List convertToDTOs(List models) {         return models.stream()                 .map(this::convertToDTO)                 .collect(toList());     }     @Override     public TodoDTO findById(String id) {         Todo found = findTodoById(id);         return convertToDTO(found);     }     @Override     public TodoDTO update(TodoDTO todo) {         Todo updated = findTodoById(todo.getId());         updated.update(todo.getTitle(), todo.getDescription());         updated = repository.save(updated);         return convertToDTO(updated);     }     private Todo findTodoById(String id) {         Optional result = repository.findOne(id);         return result.orElseThrow(() -> new TodoNotFoundException(id));     }     private TodoDTO convertToDTO(Todo model) {         TodoDTO dto = new TodoDTO();         dto.setId(model.getId());         dto.setTitle(model.getTitle());         dto.setDescription(model.getDescription());         return dto;     }} We have now created the service layer of our example application. Let's move on and create the controller class. Creating the Controller Class First, we need to create the DTO class that contains the information of a single todo entry and specifies the validation rules that are used to ensure that only valid information can be saved to the database. The source code of the TodoDTO class looks as follows:       import org.hibernate.validator.constraints.NotEmpty;import javax.validation.constraints.Size;public final class TodoDTO {     private String id;     @Size(max = Todo.MAX_LENGTH_DESCRIPTION)     private String description;     @NotEmpty     @Size(max = Todo.MAX_LENGTH_TITLE)     private String title;     //Constructor, getters, and setters are omitted} Additional Reading: The Reference Manual of Hibernate Validator 5.0.3 Second, we have to create the controller class that processes the HTTP requests send to our REST API and sends the correct response back to the client. We can do this by following these steps: Inject our service to our controller by using constructor injection. Add a create() method to our controller and implement it by following these steps: Read the information of the created todo entry from the request body. Validate the information of the created todo entry. Create a new todo entry and return the created todo entry. Set the response status to 201. Implement the delete() method by delegating the id of the deleted todo entry forward to our service and return the deleted todo entry. Implement the findAll() method by finding the todo entries from the database and returning the found todo entries. Implement the findById() method by finding the todo entry from the database and returning the found todo entry. Implement the update() method by following these steps: Read the information of the updated todo entry from the request body. Validate the information of the updated todo entry. Update the information of the todo entry and return the updated todo entry. Create an @ExceptionHandler method that sets the response status to 404 if the todo entry was not found (TodoNotFoundException was thrown). The source code of the TodoController class looks as follows:       import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseStatus;import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;import java.util.List;@RestController@RequestMapping("/api/todo")final class TodoController {     private final TodoService service;     @Autowired     TodoController(TodoService service) {         this.service = service;     }     @RequestMapping(method = RequestMethod.POST)     @ResponseStatus(HttpStatus.CREATED)     TodoDTO create(@RequestBody @Valid TodoDTO todoEntry) {         return service.create(todoEntry);     }     @RequestMapping(value = "{id}", method = RequestMethod.DELETE)     TodoDTO delete(@PathVariable("id") String id) {         return service.delete(id);     }     @RequestMapping(method = RequestMethod.GET)     List<TodoDTO> findAll() {         return service.findAll();     }     @RequestMapping(value = "{id}", method = RequestMethod.GET)     TodoDTO findById(@PathVariable("id") String id) {         return service.findById(id);     }     @RequestMapping(value = "{id}", method = RequestMethod.PUT)     TodoDTO update(@RequestBody @Valid TodoDTO todoEntry) {         return service.update(todoEntry);     }     @ExceptionHandler     @ResponseStatus(HttpStatus.NOT_FOUND)     public void handleTodoNotFound(TodoNotFoundException ex) {     }} Note: If the validation fails, our REST API returns the validation errors as JSON and sets the response status to 400. If you want to know more about this, read a blog post titled: Spring from the Trenches: Adding Validation to a REST API.That is it. We have now created a REST API that provides CRUD operations for todo entries and saves them to MongoDB database. Let’s summarize what we learned from this blog post. Summary This blog post has taught us three things: We can get the required dependencies with Maven by declaring only two dependencies: spring-boot-starter-web and spring-data-mongodb. If we are happy with the default configuration of Spring Boot, we can configure our web application by using its auto-configuration support and “dropping” new jars to the classpath. We learned to create a simple REST API that saves information to MongoDB database and finds information from it. You can get the example application of this blog post from Github.This post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on!
http://www.itnose.net/detail/6170717.html 2014-12-11 10:07   [MongoDB]

Spring Data REST入门(四):自定义查询(上)

一、自定义查询方法 通常会有这样的需求,根据给定的字段查找相应表中的数据对象。比如在前几篇博客中定义的User实体来,需要一个按照name值查到与之对应的数据对象返回,只需要在UserRopository中定义如下代码: /** * 根据用户名称查找用户 */ @RestResource(path="name",rel="name") public User findByName(@Param("name") String name); 一行非常简单的代码的代码,满足了我们的需求。我们并没有做任何实现,只是声明了一个findByName的方法而已,方法签名已经告诉Spring Data Jpa足够的信息来创建这个方法的实现了。 请求URL: http://127.0.0.1:8080/user/search/name?name= 小白鱼 返回数据: { "name" : "小白鱼", "age" : 25, "sex" : false, "_links" : { "self" : { "href" : "http://127.0.0.1:8080/user/1" }, "user" : { "href" : "http://127.0.0.1:8080/user/1{?projection}", "templated" : true } } } JPA自动生成的查询sql Hibernate: select user0_.id as id1_0_, user0_.age as age2_0_, user0_.name as name3_0_, user0_.password as password4_0_, user0_.sex as sex5_0_ from user user0_ where user0_.name=? 当创建Repository实现的时候,Spring Data会检查Repository接口的所有方法,解析方法的名称,并基于被持久化的对象来试图推测方法的目的。本质上,Spring Data定义了一组小型的领域特定语言(domain-specific language ,DSL),在这里,持久化的细节都是通过Repository方法的签名来描述的。 Spring Data能够知道这个方法是要查找User的,因为我们使用User对JpaRepository进行了参数化。方法名findByName确定该方法需要根据name属性相匹配来查找User,而name是作为参数传递到方法中来的。 findByName()方法非常简单,但是Spring Data也能处理更加有意思的方法名称。Repository方法是由一个动词、一个可选的主题(Subject)、关键词By以及一个断言所组成。在findByName()这个样例中,动词是find,断言是name,主题并没有指定,暗含的主题是User。 Spring Data允许在方法名中使用四种动词:get、read、find和count。其中,动词get、read和find是同义的,这三个动词对应的Repository方法都会查询数据并返回对象。而动词count则会返回匹配对象的数量,而不是对象本身。 在断言中,会有一个或多个限制结果的条件。每个条件必须引用一个属性,并且还可以指定一种比较操作。如果省略比较操作符的话,那么这暗指是一种相等比较操作。不过,我们也可以选择其他的比较操作,包括如下的种类: IsAfter、After、IsGreaterThan、GreaterThan IsGreaterThanEqual、GreaterThanEqual IsBefore、Before、IsLessThan、LessThan IsLessThanEqual、LessThanEqual IsBetween、Between IsNull、Null IsNotNull、NotNull IsIn、In IsNotIn、NotIn IsStartingWith、StartingWith、StartsWith IsEndingWith、EndingWith、EndsWith IsContaining、Containing、Contains IsLike、Like IsNotLike、NotLike IsTrue、True IsFalse、False Is、Equals IsNot、Not 要对比的属性值就是方法的参数。 模糊查询 @RestResource(path="nameStartsWith",rel="nameStartsWith") public List<User> findByNameStartsWith(@Param("name") String name); 需求查询以name为white开始的用户,则 查询URL为: http://127.0.0.1:8080/user/search/nameStartsWith?name=white 返回数据略。 忽略大小写查询 要处理String类型的属性时,如果需要忽略大小写则可以在方法签名中加入IgnoringCase,这样在 执行对比的时候就会不再考虑字符是大写还是小写。例如,要在name属性上忽略大小写,那么可以将方法签名改成如下的形式: @RestResource(path="nameStartsWith",rel="nameStartsWith") public List<User> findByNameStartsWithIgnoringCase(@Param("name") String name); 多条件查询 如果需要匹配多个添加则用And和Or连接,比如: @RestResource(path="nameAndAge",rel="nameAndAge") public List<User> findByNameAndAge(@Param("name")String name ,@Param("age")int age); 排序 可以在方法名称的结尾处添加OrderBy,实现结果集排序。比如可以按照User的Age降序排列 @RestResource(path="nameStartsWith",rel="nameStartsWith") public List<User> findByNameStartsWithOrderByAgeDesc(@Param("name") String name); 这里只是初步体验了所能声明的方法种类,Spring Data JPA会为我们实现这些方法。现在,我们只需知道通过使用属性名和关键字构建Repository方法签名,就能让Spring Data JPA生成方法实现,完成几乎所有能够想象到的查询。不过,Spring Data这个小型的DSL依旧有其局限性,有时候通过方法名称表达预期的查询很烦琐,甚至无法实现。如果遇到这种情形的话,Spring Data能够让我们通过@Query注解来解决问题。
http://www.itnose.net/detail/6705815.html 2017-01-12 14:55   [Spring]

Spring MVC 学习3:@RequestMapping注解和REST

和 @PathVariable 的使用 @PathVariable 映射 URL 绑定的占位符 带占位符的 URL 是 Spring3.0 新增的功能,该功能在 Spring MVC 向 REST 目标挺进发展过程中具有 里程碑的意义。 2) 通过 @PathVariable 可以将
http://www.itnose.net/detail/6658611.html 2016-11-01 01:56   [Spring]

Spring MVC REST异常处理最佳实践(上)

如果你已经使用 Spring 来构建你的应用,并且你需要提供 REST API, 那么 Spring MVC 会是你编写 REST 端一个很好的选择。 然而,由于 Spring MVC 常被用来构建用户接口,因此通过 RESTful 方式来清楚表示异常或问题并不是(那么)显而易见。因为在
http://www.itnose.net/detail/6633733.html 2016-08-29 09:23   [Spring]

基于Spring MVC(REST API)做单元测试(mockito)

最近在公司用的Spring Mvc REST API框架做了一个项目,并且做了基于Spring的单元测试,今天先讲一下基于Spring框架的单元测试,测试使用的是Spring自带的test组件,再结合Mockito一起编写测试案例,以下示例会包括Controller和Service,由于
http://www.itnose.net/detail/6619170.html 2016-08-05 11:35   [Spring]

  1  2  3  4  5 下一页>