Spring-Data-REST修改默认配置

简介: 在上一篇中除去配置类和实体类,写了两行代码,就实现了RESTful风格的接口,但在实际使用时,还需要一些额外的处理,比如在返回的数据中,password这类敏感字段是不应该返回的;删除操作,实际需求不是硬删除只是更新一个删除状态;保存对象操作之前需要做相应的数据校验和数据格式的转换等等,自动转换成REST服务,是否支持自定义功能?在上一篇中除去配置类和实体类,写了两行代码,就实现了RESTful风格的接口,但在实际使用时,还需要一些额外的处理,比如在返回的数据中,password这类敏感字段是不应该返回的;删除操作,实际需求不是硬删除只是更新一个删除状态;保存对象操作之前需要做相应的数据校验

背景


上一篇中除去配置类和实体类,写了两行代码,就实现了RESTful风格的接口,但在实际使用时,还需要一些额外的处理,比如在返回的数据中,password这类敏感字段是不应该返回的;删除操作,实际需求不是硬删除只是更新一个删除状态;保存对象操作之前需要做相应的数据校验和数据格式的转换等等,自动转换成REST服务,是否支持自定义功能?

分页+排序查询(这个与以往的习惯有点不同)


http://localhost:8080/user?sort=id,desc&size=2

sort desc 这类关键字是否可以自定义?因为运维方面会对这些关键字做防SQL注入(waf)
1. {
2.   "_embedded": {
3.     "users": [
4.       {
5.         "userName": "Yezhwi4",
6.         "password": "123",
7.         "phone": "12345678901",
8.         "locked": 0,
9.         "_links": {
10.           "self": {
11.             "href": "http://localhost:8080/user/17"
12.           },
13.           "user": {
14.             "href": "http://localhost:8080/user/17"
15.           }
16.         }
17.       },
18.       {
19.         "userName": "Yezhwi5",
20.         "password": "123",
21.         "phone": "12345678901",
22.         "locked": 0,
23.         "_links": {
24.           "self": {
25.             "href": "http://localhost:8080/user/16"
26.           },
27.           "user": {
28.             "href": "http://localhost:8080/user/16"
29.           }
30.         }
31.       }
32.     ]
33.   },
34.   "_links": {
35.     "first": {
36.       "href": "http://localhost:8080/user?page=0&size=2&sort=id,desc"
37.     },
38.     "self": {
39.       "href": "http://localhost:8080/user"
40.     },
41.     "next": {
42.       "href": "http://localhost:8080/user?page=1&size=2&sort=id,desc"
43.     },
44.     "last": {
45.       "href": "http://localhost:8080/user?page=5&size=2&sort=id,desc"
46.     },
47.     "profile": {
48.       "href": "http://localhost:8080/profile/user"
49.     }
50.   },
51.   "page": {
52.     "size": 2,
53.     "totalElements": 11,
54.     "totalPages": 6,
55.     "number": 0
56.   }
57. }

自定义查询方法


根据给定的字段查找相应表中的数据对象。比如在上一篇中定义的User实体,需要一个按照userName(假如数据库中唯一)值查到与之对应的数据对象返回,只需要在UserRopository中定义如下代码:

import com.gemantic.model.User;
import com.google.common.base.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
/**
 * @author Yezhiwei
 * @date 17/12/16
 */
@RepositoryRestResource(path = "user")
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUserName(@Param("userName") String userName);
}

所有的查询方法,默认转成search路径下,如: http://localhost:8080/user/search/findByUserName?userName=Yezhiwei

上图中自动转成的URL是按方法名,若要更改该查询方法所暴露的URL,在方法上使用

@RestResource注释
1. @RestResource(path = "name", rel = "name")
2. Optional<User> findByUserName(@Param("userName") String userName);

输入 http://localhost:8080/user/search/ 查看user下的所有查询方法有哪些:

查看资源user下所有查询方法 /user/search

path = "name" 将路径参数findByUserName转为name /user/search/name

rel = "name" 更改参数findByUserName转为name

多条件查询


如果匹配多个条件查询,则用And和Or连接,比如:

import com.gemantic.model.User;
import com.google.common.base.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.data.rest.core.annotation.RestResource;
import java.util.List;
/**
 * @author Yezhiwei
 * @date 17/12/16
 */
@RepositoryRestResource(path = "user")
public interface UserRepository extends JpaRepository<User, Long> {
    ...
    @RestResource(path = "nameAndPhone", rel = "nameAndPhone")
    List<User> findByUserNameAndPhone(@Param("userName") String userName, @Param("phone") String phone);
}

排序


可以在方法名称的结尾处添加OrderBy,实现结果集排序。比如可以按照User的userName降序排列

import com.gemantic.model.User;
import com.google.common.base.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.data.rest.core.annotation.RestResource;
import java.util.List;
/**
 * @author Yezhiwei
 * @date 17/12/16
 */
@RepositoryRestResource(path = "user")
public interface UserRepository extends JpaRepository<User, Long> {
    ...
    @RestResource(path = "nameStartsWith", rel = "nameStartsWith")
    List<User> findByUserNameStartsWithOrderByUserNameDesc(@Param("userName") String userName);
}

隐藏某个字段


比如在实体对象User中,不希望password序列化为JSON,Spring Data REST默认使用的是JackSon,则我们就可以在需要隐藏的字段添加@JsonIgnore即可

@Data
@Entity
public class User {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String userName;
    @JsonIgnore
    private String password;
    private String phone;
    private Integer locked;
}

隐藏自定义的查询方法


只需要在方法上添加 @RestResource(exported=false) 即可,如:

/**
 * @author Yezhiwei
 * @date 17/12/16
 */
@RepositoryRestResource(path = "user")
public interface UserRepository extends JpaRepository<User, Long> {
//    @RestResource(path = "name", rel = "name")
    @RestResource(exported = false)
    Optional<User> findByUserName(@Param("userName") String userName);
    @RestResource(path = "nameAndPhone", rel = "nameAndPhone")
    List<User> findByUserNameAndPhone(@Param("userName") String userName, @Param("phone") String phone);
    @RestResource(path = "nameStartsWith", rel = "nameStartsWith")
    List<User> findByUserNameStartsWithOrderByUserNameDesc(@Param("userName") String userName);
}

屏蔽自动化方法(repository CRUD)


extendsCrudRepository

在实际生产环境中,不会真正删除用户数据,此时不希望DELETE的提交方式生效,可以添加@RestResource注解,并设置exported=false,即可屏蔽Spring Data REST的自动化方法 ,只需要写如下代码:

/**
 * @author Yezhiwei
 * @date 17/12/16
 */
@RepositoryRestResource(path = "user")
public interface UserRepository extends CrudRepository<User, Long> {
    ...
    @RestResource(path = "nameStartsWith", rel = "nameStartsWith")
    List<User> findByUserNameStartsWithOrderByUserNameDesc(@Param("userName") String userName);
    @Override
    @RestResource(exported = false)
    void delete(Long id);
}

修改对象返回值json数据中的key


默认是User对象的属性,在一些特殊情况下,需要修改json返回值中的key,需要定义如下代码:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.rest.core.config.Projection;
/**
 *
 */
@Projection(name = "vu",types = User.class)
public interface VirtualUser {
    @Value("#{target.userName}-#{target.phone}")
    String getFullInfo();
    @Value("#{target.locked}")
    Integer getStatus();
}

这里把User中的userName和phone合并成一列,locked重新命名为stauts,这里需要注意方法名前面一定要加get,不然无法序列化为JSON数据。启动服务,试一试

http://localhost:8080/user/1

http://localhost:8080/user/1?projection=vu

参考 Customizing Spring Data REST

相关文章
|
1月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
1月前
|
Java 关系型数据库 MySQL
Spring Boot自动配置:魔法背后的秘密
Spring Boot 自动配置揭秘:只需简单配置即可启动项目,背后依赖“约定大于配置”与条件化装配。核心在于 `@EnableAutoConfiguration` 注解与 `@Conditional` 系列条件判断,通过 `spring.factories` 或 `AutoConfiguration.imports` 加载配置类,实现按需自动装配 Bean。
|
1月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
3月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 &gt; Java系统属性 &gt; application.properties &gt; application.yml &gt; application.yaml。
730 0
|
6天前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
3天前
|
XML 前端开发 Java
一文搞懂 Spring Boot 自动配置原理
Spring Boot 自动配置原理揭秘:通过 `@EnableAutoConfiguration` 加载 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports` 中的配置类,结合 `@Conditional` 按条件注入 Bean,实现“开箱即用”。核心在于约定大于配置,简化开发。
91 0
|
1月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
321 4
|
1月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
116 0
探索Spring Boot的@Conditional注解的上下文配置
|
6月前
|
安全 Java API
深入解析 Spring Security 配置中的 CSRF 启用与 requestMatchers 报错问题
本文深入解析了Spring Security配置中CSRF启用与`requestMatchers`报错的常见问题。针对CSRF,指出默认已启用,无需调用`enable()`,只需移除`disable()`即可恢复。对于`requestMatchers`多路径匹配报错,分析了Spring Security 6.x中方法签名的变化,并提供了三种解决方案:分次调用、自定义匹配器及降级使用`antMatchers()`。最后提醒开发者关注版本兼容性,确保升级平稳过渡。
751 2
|
7月前
|
缓存 Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
本文介绍了在Spring Boot中配置Swagger2的方法。通过创建一个配置类,添加`@Configuration`和`@EnableSwagger2`注解,使用Docket对象定义API文档的详细信息,包括标题、描述、版本和包路径等。配置完成后,访问`localhost:8080/swagger-ui.html`即可查看接口文档。文中还提示了可能因浏览器缓存导致的问题及解决方法。
846 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置