use spring-boot internal @Controllers with @Reques

2019-09-14 15:46发布

问题:

I am building a back-end rest api with spring boot.

Entity:

@Entity
public class Club {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @NotNull
    @Column(unique=true)
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Repository:

@RepositoryRestResource
public interface ClubRepository extends JpaRepository<Club, Long>, JpaSpecificationExecutor<Club> {

}

This alone exposes a rest endpoint at http://host/clubs, great. Now, I'd like to allow some parameters in the url for search purposes, so I started following the instructions of http://www.baeldung.com/rest-api-search-language-spring-data-specifications.

But they end-up creating a custom @Controller to pass the request params:

@Controller
public class ClubController {

    @Autowired
    private ClubRepository repo;

    @RequestMapping(method = RequestMethod.GET, value = "/clubs")
    @ResponseBody
    public List<Club> search(@RequestParam(value = "search") String search) {
        /* ... */
        return repo.findAll(spec);
    }
}

So you see, they end up calling the findAll method of the repository, just passing a specification they build based on the query parameter. Easy enough, but really I'd love to not have to create additional controllers for each of my domain objects. In other words, is there a way to provide this search feature by directly annotating (for example) the @Entity, or overriding methods (like the findAll method) in the repository?

回答1:

A better approach is to use QueryDsl rather than the criteria API. Spring Data and, by extension, Spring Data Rest will then give you a lot of excellent functionality 'for free' other than some basic configuration.

https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#spring-data-rest

https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

One configured your repository interface simply becomes:

@RepositoryRestResource
public interface ClubRepository extends JpaRepository<Club, Long>, QueryDslPredicateExecutor<Club> {

}

An endpoint can then be queried using a dynamic combination of parameters:

e.g.

http://host/clubs?name=someName

http://host/clubs?name=someName&otherProperty=X&sort=name,desc

No further code is required for this i.e. no custom controller, no specifications and no query methods.

For configuring Maven simply add the following to the POM in the module containing your entities: this will generate the necessary 'query' classes.

<dependencies>
    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
        <version>${querydsl.version}</version>
    </dependency>
    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>${querydsl.version}</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>com.mysema.maven</groupId>
            <artifactId>apt-maven-plugin</artifactId>
            <version>1.1.3</version>
            <executions>
                <execution>
                    <goals>
                        <goal>process</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>target/generated-sources/java</outputDirectory>
                        <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>