The REST API can be easily implemented as follows: The MongoDb seamless integration can be implemented as follows: Use JWT and Spring Security to protect REST apis

Find the familiar Controller, Service

Where’s the Controller?

For many students who are used to Spring development, the routine of Controller, Service and DAO will suddenly disappear, which will make them feel uncomfortable. Well, those things are still there, but in the simpler case, they’re just the things that the system does behind the scenes for you. In this section we will first see how to summon the Controller back. What are the benefits of summoning back? First, we can customize the path of the API URL, and second, we can do some processing with the parameters and the returned JSON structure.

To make TodoController work with TodoRepository, we need to reference TodoRepository in TodoController.

public class TodoController {
    @Autowired
    private TodoRepository repository;
    // omit other parts
}Copy the code

The @autowired modifier is used to do dependency injection. The above usage is called field injection, which directly does the injection of a class member. But Spring now encourages constructors for injection, so let’s look at constructor injection methods:

public class TodoController {

    private TodoRepository repository;

    @Autowired
    public TodoController(TodoRepository repository){
        this.repository = repository;
    }
    // omit other parts
}Copy the code

Of course we need to mark it @restController in order for Spring to know that this is a Controller that supports the REST API. Because the default path map is plural at the resource root, and because todo ends in an o after a consonant, English convention maps to todoes. But here it’s more comfortable to use Todos than Todoes, so we’ll use another @requestMapping (“/todos”) to customize the path. The other methods in the Controller are simpler: add, delete, modify, and query using the repository method.

package dev.local.todo;

import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/todos")
public class TodoController {

    private TodoRepository repository;

    @Autowired
    public TodoController(TodoRepository repository){
        this.repository = repository;
    }

    @RequestMapping(method = RequestMethod.GET)
    public List<Todo> getAllTodos(@RequestHeader(value = "userId") String userId) {
        return repository.findByUserId(new ObjectId(userId));
    }

    @RequestMapping(method = RequestMethod.POST)
    Todo addTodo(@RequestBody Todo addedTodo) {
        return repository.insert(addedTodo);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Todo getTodo(@PathVariable String id) {
        return repository.findOne(id);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    Todo updateTodo(@PathVariable String id, @RequestBody Todo updatedTodo) {
        updatedTodo.setId(id);
        return repository.save(updatedTodo);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    Todo removeTodo(@PathVariable String id) {
        Todo deletedTodo = repository.findOne(id);
        repository.delete(id);
        returndeletedTodo; }}Copy the code

A few more points need to be made in the above code:

  1. Why tag on a class@RequestMapping("/todos")You’ll need to add it later on each method@RequestMapping? Class defined above@RequestMappingIs applied to all methods by default, but if we find that a method needs its own special value, we need to define the mapping parameters for that method. Like in the example aboveaddTodoThe path is alsotodosBut the way to ask for a Request isPOSTSo we gave it@RequestMapping(method = RequestMethod.POST). butgetTodoThe path of the method should betodos/:id, and then we’re going to give@RequestMapping(value = "/{id}", method = RequestMethod.GET)
  2. The parameters that these methods accept also use various modifiers,@PathVariableIndicates that the parameter is derived from the path, and@RequestBodyIndicates that the parameter should be taken from the Http RequestbodyIn the same way@RequestHeaderIndicates that the parameter is defined in the Header of the Http Request.

Before we can test, we also need to mark TodoRepository with @Repository so that Spring can find the class during dependency injection.

package dev.local.todo;

import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;


/** * Created by wangpeng on 2017/1/26. */
@Repository
public interface TodoRepository extends MongoRepository<Todo.String>{
    List<Todo> findByUserId(ObjectId userId);
}Copy the code

Here’s a PostMan test:

Test the Controller

The Service? Where is it?

If you are familiar with Spring, you may ask, “What we just did is the Controller accesses Data directly. Isolation is not enough.” In fact, I think a lot of the time, this kind of simple design is good, because the business hasn’t reached that stage, too complicated design actually doesn’t make much sense. But let’s go step by step and get that familiar feeling back.

It’s easy to go back to the familiar pattern. Create a new TodoService interface and define the current add, delete, change, and check operations:

public interface TodoService {
    Todo addTodo(Todo todo);
    Todo deleteTodo(String id);
    List<Todo> findAll(String userId);
    Todo findById(String id);
    Todo update(Todo todo);
}Copy the code

In case we use MySQL and other potential “extensibility” in the future, we named the implementation of the interface MongoTodoServiceImpl and then took most of the Controller code and changed it. Of course, so that the system can find this dependency and inject it into the required class, we mark it as @service

@Service
public class MongoTodoServiceImpl implements TodoService{
    private final TodoRepository repository;

    @Autowired
    MongoTodoServiceImpl(TodoRepository repository) {
        this.repository = repository;
    }

    @Override
    public Todo addTodo(Todo todo) {
        return repository.insert(todo);
    }

    @Override
    public Todo deleteTodo(String id) {
        Todo deletedTodo = repository.findOne(id);
        repository.delete(id);
        return deletedTodo;
    }

    @Override
    public List<Todo> findAll(String userId) {
        return repository.findByUserId(new ObjectId(userId));
    }

    @Override
    public Todo findById(String id) {
        return repository.findOne(id);
    }

    @Override
    public Todo update(Todo todo) {
        repository.save(todo);
        returntodo; }}Copy the code

Finally, change all the methods in Controller to simple calls to Service and you’re done.

public class TodoController {

    private TodoService service;

    @Autowired
    public TodoController(TodoService service){
        this.service = service;
    }

    @RequestMapping(method = RequestMethod.GET)
    public List<Todo> getAllTodos(@RequestHeader(value = "userId") String userId) {
        return service.findAll(userId);
    }

    @RequestMapping(method = RequestMethod.POST)
    Todo addTodo(@RequestBody Todo addedTodo) {
        return service.addTodo(addedTodo);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Todo getTodo(@PathVariable String id) {
        return service.findById(id);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    Todo updateTodo(@PathVariable String id, @RequestBody Todo updatedTodo) {
        updatedTodo.setId(id);
        return service.update(updatedTodo);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    Todo removeTodo(@PathVariable String id) {
        returnservice.deleteTodo(id); }}Copy the code

To be honest, if every simple class did this, I would be deeply deviating from the intent of Spring Boot, although you can give me a thousand reasons why it would be good to do so. Similarly, daOs or Dtos are easy to write, but I recommend enjoying the benefits of Spring Boot until the business is more complex.

This chapter code: github.com/wpcfan/spri…

The REST API can be easily implemented as follows: The MongoDb seamless integration can be implemented as follows: Use JWT and Spring Security to protect REST apis