This article mainly introduces Spring Boot (3) to retrieve the familiar Controller and Service. Friends in need can refer to
Retrieve the familiar Controller. Where is the Service Controller?
For many students who are used to Spring development, they will feel uncomfortable if the routines of Controller, Service, and DAO are suddenly gone. In fact, these things still exist, but in simpler scenarios, these have become things that the system does for you behind the scenes. In this section, we will first look at how to summon the Controller back. What are the benefits of calling back? First, we can customize the path of the API URL, and secondly, we can do certain processing on the parameters and the returned json structure.
If we want TodoController to work with TodoRepository, of course we need to reference TodoRepository in TodoController.
public class TodoController { @Autowired private TodoRepository repository; //省略其它部分 }
@Autowired This modifier is used for dependency injection. The above usage is called field injection, which directly injects class members. But Spring now encourages the use of constructor for injection, so let’s take a look at the constructor injection method:
public class TodoController { private TodoRepository repository; @Autowired public TodoController(TodoRepository repository){ this.repository = repository; } //省略其它部分 }
Of course, we want to let Spring know that this is a REST API that supports Controller, you still need to mark it as @RestController. Since the default path mapping will use the plural form at the resource root, and since todo ends with o after the consonant, according to English custom, it will be mapped to todoes. But it’s more comfortable to use todos than todoes here, so we use another @RequestMapping("/todos") to customize the path. The other methods in this Controller are relatively simple, just use the methods in the repository to add, delete, modify and check.
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); return deletedTodo; } }
A few more points need to be explained in the above code:
Why mark @RequestMapping("/todos") on the class and then on each method? Need to add @RequestMapping? The parameters of @RequestMapping defined above the class will be 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 of this method. For example, in the above example, addTodo, the path is also todos, but the required Request method is POST, so we gave @RequestMapping(method = RequestMethod.POST). But the path of the getTodo method should be todos/:id. At this time, we need to give @RequestMapping(value = "/{id}", method = RequestMethod.GET)
The parameters accepted by these methods also use various modifications symbol, @PathVariable indicates that the parameters are obtained from the path, while @RequestBody indicates that the parameters should be parsed from the body of the Http Request, and similar @RequestHeader indicates that the parameters are defined in the Header of the Http Request.
Before we can test, we also need to use @Repository to mark TodoRepository so that Spring can find this 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); }
Next, you can use PostMan
to do a test:
Test it
What about the Controller Service? Where?
Children who are familiar with Spring will definitely ask, what we did just now is equivalent to the Controller accessing the Data directly, and the isolation is not enough. In fact, I think that many times, this kind of simple design is quite good, because the business has not reached that stage yet, and an overly complex design actually does not make much sense. But here we will practice it step by step to get back the familiar feeling.
It couldn’t be easier to return to the original familiar mode. Create a new TodoService Interface and define the current operations of adding, deleting, modifying and checking:
public interface TodoService { Todo addTodo(Todo todo); Todo deleteTodo(String id); List<Todo> findAll(String userId); Todo findById(String id); Todo update(Todo todo); }
To prevent us from doing so in the future Using potential "scalability" such as MySQL, we name the implementation of this interface MongoTodoServiceImpl, and then just take most of the code in the Controller and change it. Of course, in order for the system to 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); return todo; } }
Finally, change all the methods in the Controller to simple calls using 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) { return service.deleteTodo(id); } }
To be honest, if every simple class is written like this, I will deeply deviate from the intention of Spring Boot, although you can cite 1,000 reasons for doing so. Similarly, DAO or DTO is very simple to write, but I still recommend enjoying the convenience that Spring Boot brings to us until the business is not complicated.
【Related Recommendations】
2. Geek Academy Java Video Tutorial
The above is the detailed content of Detailed explanation of referencing TodoRepository in TodoController. For more information, please follow other related articles on the PHP Chinese website!