I have been studying MVC for two years, but some concepts are still vague. I hope I can find the answer here.
I once saw someone say that the Controller is not responsible for data processing, and it is all handled by our Service. Whatever data type is returned from the front end of the web page, the data type is directly forwarded to the Service, and then the Service handles it; but again There is another voice saying that sometimes multiple Services are called at the same time. If the object is encapsulated in the Controller, it will be avoided multiple times in the Service method.
Another question is about the interaction between Controller and Service.
In order to ensure good customer interaction on the front end, we often return some error prompts to the front end through the Controller, such as the user name already exists, the user name and password do not match, etc. However, we process the business logic in the Service layer. If we set the return value of a login(String username, String password) method to boolean, we cannot return multiple errors. However, if we return the String type, we need to set some basic settings. dictionary.
My own "fancy idea" is that I throw some custom RuntimeExceptions in the Service, and then use TryCatch in the Controller to handle different errors, but I think this way of throwing exceptions is not good. Appropriate. I have been confused recently and am about to start working on my next project. I hope you can help me clear up my confusion.
grateful.
Our project is divided into three levels:
Presentation layer: Spring MVC, responsible for receiving Http requests, displaying (returning) results, and simple verification
App layer: Provides application layer functions, such as import, export, and complex verification
Domain layer: handles business logic, such as some Services
The calling sequence is single: Controller->App->Domain
And the perception relationship is: Controller->App->Domain, that is, the lower layer does not perceive the upper layer
Let me answer your first question first:
Can I understand the first question you mentioned to mean that the parameters received by Http request are not Object, but a bunch of basic types, but the parameters received by your Service are Object. The correct approach should be to convert the "raw" parameter into an Object object in the Controller, and then call the Service.
Why is this correct? Because Service belongs to the Domain layer, which contains business logic, the parameters it accepts should be designed according to your own needs. You should not consider the parameters from the Web layer, so that they can be reused in different scenarios.
For example, your Service should be reusable in different presentation layer environments:
In a web program, the parameters passed by the user are given to you in the form of POST/GET
In a Web service program, the parameters passed by the user are json or SOAP
In a Swing program, the parameters passed by the user are strings
If you bind Service to a specific presentation layer environment, then its method parameters will definitely be unstable, resulting in the inability to reuse.
Similarly, the return value of Service should not be bound to the specific scenario.
At the Spring MVC level, Controller can easily convert parameters into Object, related documents
Second question:
This question can be divided into three parts:
1) Where to do simple verification such as parameter length limit, non-empty judgment, etc.?
Simple verification is done using the mechanism provided by Spring MVC itself, related documents, related documents
2) Where is the verification done in parallel with the business logic of the Service itself, such as determining whether the user’s account is disabled when placing an order?
I tend to do these logical checks on the App layer. The Controller calls the App, and the App calls two different Services to weave the business togetherI think
Controller
不负责处理数据是正确的, 因为在spring-mvc
中Controller
是不能复用的, 但是如果你把业务逻辑抽象成Service
, 那么这个Service
can be reused.As for what you said "encapsulating the object in the Controller, you don't need to encapsulate it multiple times in the Service method", I don't quite understand what it means. What parameters do you give for each
Service
需要什么参数,Controller
? As for whether the required parameters need to be encapsulated Once you become the target, you can weigh it yourself.What you said
login(String username,String password)
, 你想抽象成Service
用异常处理处理多种不同的结果, 这个我觉得完全没有问题, 而且我觉得非常好啊, 很多认证框架都用的这种方式, 至少我看的apache-shiro
is to use exceptions to handle different situations of authentication failure.There is no standard answer to the first question. It is better to analyze the specific situation and make the logic layering clear and easy to maintain.
As for the second question, the interaction you gave here is subject to permission control. Generally, filter, aop, proxy, reflection, etc. can be used to achieve code closure. Exceptions are also thrown once in these centralized control codes. That's fine, but I find it cumbersome to hardcode it directly in the Controller. The Service layer is more about calling the Dao layer methods to implement some complex business logic processing involving multiple tables. Transactions are also placed on this layer (of course the framework has done all this now), so the Service layer The layer generally does not throw exceptions (parameter verification is done in the Controller and previous layers, so no business-related exceptions occur, and Dao blocks underlying exceptions related to the database).
Of course, this is a personal opinion, there is no fixed formula, as I said, it’s good if the layers are clear and easy to maintain.
1. Controller is singleton by default, but it can be replaced by @Scope(value = "prototype")
2. Login can return int, add an enumeration by yourself
3. It is stipulated that the logic is processed in the Service layer. It depends on the business. It is better to have less code redundancy and to optimize it
Everyone has different opinions. What is more important in development is optimization and modification and reducing redundancy, rather than what must be done. . .
1. Controller should not design business logic as much as possible, only involve interaction
2. Service is reusable business logic
3. Controller is the superior caller of Service
4. In your case, you can return a fixed value in Service Return the value, make a judgment at the Controller layer, and throw the corresponding exception you want.
Of course, this is just our current approach, please share it. . .
You can read my article
AOP, MVC - Spring learning and reflection on CodeIgniter /a/11...
It is recommended that the logic be placed in the service. We are currently working on a distributed microservice architecture. We used to put it on the controller layer. When we split it, we basically re-created it. In addition, some interfaces that apps need to use cannot be shared if they are placed on the controller. It hurts. Bar?
Whether the encapsulated object is in the Controller or the Service depends on the specific situation. I personally think that if it is a simple parameter, it is perfectly fine to encapsulate it in the Controller. However, if it is placed in the Service, it will appear very redundant and lead to the versatility of the Service. Deterioration; for the second question, it is not allowed to use enumeration or different status codes to make judgments and throw exceptions on the left side of the Controller. You can completely define your own set of exception handling mechanisms and throw them directly in the Service layer. The project has targeted this A business-like exception handling mechanism that directly returns the Service error message and error code to the View layer, allowing the client to handle it based on the status code and error message