Summary of Model layer analysis
In the last two blogs, I mainly analyzed the code of the entity class Product and the parent class inherited by the Product class. To sum up, Jpress is mainly a framework established on jfinal and Jboot, so it is necessary to understand jfinal and Jboot
JAVA speed WEB+ORM framework JFinal_Demo
JFinal is a high-speed WEB + ORM framework based on Java language. Its core design goal is rapid development, less code, simple learning, powerful function, lightweight, easy to expand and Restful. While having all the advantages of Java language, it also has the development efficiency of dynamic languages such as ruby and python!
JFinal has the following main features
MVC Architecture, exquisite design and simple use follow COC Principle, support zero configuration, none XML original Db + Record Mode, flexible and convenient ActiveRecord Support, making database development extremely fast Minimalist, powerful and high-performance template engine Enjoy,Master 90 in ten minutes% usage Automatically load modified Java File, and there is no need to restart the service during the development process AOP Support, the interceptor configuration is flexible and powerful Plugin Architecture, strong scalability Multi view support Enjoy,FreeMarker,JSP,Velocity Powerful Validator Back end verification function Fully functional and traditional SSH Most of the core functions of the framework Small size, only 777 KB,And there is no third-party dependence
The following is an example of JFinal implementing Blog management:
- Controller (supports Enjoy, JSP, Velocity, JSON, etc., and custom view rendering)
@Before(BlogInterceptor.class) public class BlogController extends Controller { @Inject BlogService service; public void index() { set("blogPage", service.paginate(getParaToInt(0, 1), 10)); render("blog.html"); } public void add() { } @Before(BlogValidator.class) public void save() { getModel(Blog.class).save(); redirect("/blog"); } public void edit() { set("blog", service.findById(getParaToInt())); } @Before(BlogValidator.class) public void update() { getModel(Blog.class).update(); redirect("/blog"); } public void delete() { service.deleteById(getParaToInt()); redirect("/blog"); } }
2. All services and sql are placed in the Service layer
public class BlogService { private Blog dao = new Blog().dao(); public Page<Blog> paginate(int pageNumber, int pageSize) { return dao.paginate(pageNumber, pageSize, "select *", "from blog order by id asc"); } public Blog findById(int id) { return dao.findById(id); } public void deleteById(int id) { dao.deleteById(id); } }
3. Model (no xml, no annotation, no attribute)
public class Blog extends Model<Blog> { }
4.Validator(API guided verification is N times more convenient than xml verification, and code checking is not easy to make mistakes)
public class BlogValidator extends Validator { protected void validate(Controller controller) { validateRequiredString("blog.title", "titleMsg", "Please enter Blog title!"); validateRequiredString("blog.content", "contentMsg", "Please enter Blog content!"); } protected void handleError(Controller controller) { controller.keepModel(Blog.class); } }
5. Interceptor (this demo is only an example, and this demo does not need this interceptor)
public class BlogInterceptor implements Interceptor { public void intercept(Invocation inv) { System.out.println("Before invoking " + inv.getActionKey()); inv.invoke(); System.out.println("After invoking " + inv.getActionKey()); } }
Learning of JFinal official documents
JFinal simplified AOP: fast and convenient
Traditional AOP implementation requires the Introduction of a large number of complex and redundant concepts, such as Aspect, Advice, Joinpoint, Poincut, Introduction, Weaving, Around, etc., and the Introduction of IOC containers and a large number of XML or annotation for component assembly.
Traditional AOP not only has high learning cost, low development efficiency and poor development experience, but also affects the system performance, especially the slow start of the project in the development stage, which greatly affects the development efficiency.
JFinal adopts the extremely fast AOP design, focuses on the core goal of AOP, and reduces the concept to the extreme. There are only three concepts: Interceptor, Before and Clear, and there is no need to introduce IOC or use verbose XML.
Because JFinal does not use a lot of XML files, there will be no clue when analyzing Jpress at the beginning, because many functions and codes are encapsulated by JFinal and Jboot
Interceptor
Interceptor can intercept methods and provide an opportunity to add aspect code before and after methods to achieve the core goal of AOP. The interceptor interface only defines a method public void intercept(Invocation inv). The following is a simple example:
public class DemoInterceptor implements Interceptor { public void intercept(Invocation inv) { System.out.println("Before method invoking"); inv.invoke(); System.out.println("After method invoking"); } }
The DemoInterceptor in the above code will intercept the target method and output text to the console before and after the target method call. inv.invoke()
This line of code is a call to the target method. Inserting aspect code before and after this line of code can easily realize AOP.
As the only parameter in the intercept method of the Interceptor interface, Invocation provides many convenient methods for use in the Interceptor. The following are the methods in Invocation:
Interceptor It is globally shared, so if you want to use attributes in it, you need to ensure that their attributes are thread safe. The following code will be wrong:
public class MyInterceptor implements Interceptor { private int value = 123; public void intercept(Invocation inv) { // Multithreading will access the value value concurrently, causing confusion value++; inv.invoke(); } }
As shown in the above code, the value attribute will be accessed by multiple threads, causing thread safety problems.
Before
Before annotation is used to configure interceptors. This annotation can configure interceptors at Class and Method levels. The following is a code example:
// Configure a Class level interceptor, which will intercept all methods in this Class @Before(AaaInter.class) public class BlogController extends Controller { // Configure multiple Method level interceptors to intercept only this Method @Before({BbbInter.class, CccInter.class}) public void index() { } // The Method level interceptor is not configured, but will be intercepted by the Class level interceptor aainter public void show() { } }
As shown in the above code, Before can configure interceptors at Class level and Method level. The former will intercept all methods in this Class, and the latter only intercepts this Method. In addition, Before can configure multiple interceptors at the same time, just separate multiple interceptors with commas in braces.
In addition to Class and Method level interceptors, JFinal also supports global interceptors and Routes interceptors. Global interceptors are divided into control layer global interceptors and business layer global interceptors. The former intercepts all Action methods of the control layer and the latter intercepts all methods of the business layer.
The global interceptor needs to be configured in YourJFinalConfig. The following is a configuration example:
public class YourJFinalConfig extends JFinalConfig { public void configInterceptor(Interceptors me) { // Add control layer global interceptor me.addGlobalActionInterceptor(new GlobalActionInterceptor()); // Add business layer global interceptor me.addGlobalServiceInterceptor(new GlobalServiceInterceptor()); // The method reserved for compatibility with the old version has exactly the same function as addGlobalActionInterceptor me.add(new GlobalActionInterceptor()); } }
When a Method is intercepted by multiple levels of interceptors, the execution order of each level of interceptors is: Global, Routes, Class and Method. If there are multiple interceptors in the same level, the execution order in the same level is: the one configured in front is executed first.
Clear
Interceptors are divided into four levels from top to bottom: Global, Routes, Class and Method. Clear is used to clear interceptors above their own level.
Clear declares that Global, Routes and Class will be cleared in the Method layer. Clear declares that Global and Routes will be cleared in the Class layer. When the clear annotation carries parameters, the interceptors specified in the target layer will be cleared.
In some application scenarios, Global or Class interceptors need to be removed. For example, a background management system is configured with a Global permission interceptor, but its login action must be cleared, otherwise the login operation cannot be completed. The following is a code example:
// The login method needs to remove the permission interceptor to log in normally @Before(AuthInterceptor.class) public class UserController extends Controller { // AuthInterceptor has been cleared by Clear and will not be blocked @Clear public void login() { } // This method will be intercepted by AuthInterceptor public void show() { } }
When the Clear annotation has parameters, the specified interceptor can be cleared. The following is a more comprehensive example:
@Before(AAA.class) public class UserController extends Controller { @Clear @Before(BBB.class) public void login() { // Global and Class level interceptors will be cleared, but the BBB declared on this method will not be affected } @Clear({AAA.class, CCC.class})// Clear the specified interceptor AAA and CCC @Before(CCC.class) public void show() { // Although the Clear annotation specifies to Clear CCC, it cannot be cleared because the Clear operation is only for layers above this layer } }
The above clearing is used for method and can also be used for class, for example:
@Clear(AAA.class) public class UserController { public void index() { ... } }
As shown above, @ Clear(AAA.class) will clear the AAA.java interceptor configured in the upper layer, that is, the Global and Route layers.
Inject dependency injection
@Bean public class ProductServiceProvider extends JbootServiceBase<Product> implements ProductService { private static final String DEFAULT_ORDER_BY = "order_number desc,id desc"; @Inject private UserService userService; @Inject private ProductCommentService commentService; @Inject private ProductCategoryService categoryService; }
The @ Inject annotation can be used to Inject dependent objects into the Controller and Interceptor. The injection function requires the following configuration:
public void configConstant(Constants me) { // Enable the injection of jfinal web project components Controller, Interceptor and Validator me.setInjectDependency(true); // Enable injection of superclasses. When it is not enabled, it can be injected through Aop.get(...) in the superclass me.setInjectSuperClass(true); }
The above me.setInjectDependency(true) is only a configuration for jfinal web components. Aop.get(...) and Aop.inject(...) can support injection without configuration.
After configuration, it can be used in the controller, for example:
public class AccountController { @Inject AccountService service; // Dependent objects will be injected here public void index() { service.justDoIt(); // Call the method of the injected object } }
@Inject can also be used for attribute injection of interceptors, for example:
public class MyInterceptor implements Interceptor { @Inject Service service; // Dependent objects will be injected here public void intercept(Invocation inv) { service.justDoIt(); // Call the method of the injected object inv.invoke(); } }
The premise of Inject injection is that the creation of objects of classes annotated with @ Inject is taken over by jfinal, so jfinal
To have the opportunity to Inject it. For example, jfinal takes over the creation of Controller, Interceptor and Validator, so @ Inject can be used in these three components.
If the object to be created is not taken over by jfinal, you can use the Aop.get(...) method to create and inject dependent objects, for example:
public class MyKit { static Service service = Aop.get(Service.class); public void doIt() { service.justDoIt(); } }
Since the creation of MyKit is not taken over by jfinal, @ Inject cannot be used for dependency injection. The creation and assembly of Controller and Interceptor are taken over by jfinal, so @ Inject can be used to Inject dependencies.
With Aop.get(...), you can create objects anywhere and inject the created objects. In addition, you can use Aop.inject(...) to only inject dependencies into objects without creating objects.