Teach you how to develop dynamic web projects (3)

This chapter describes how to develop business. For example, we need to develop a contact business, display the contact list, add contacts, modify contact information, and delete contacts. All the development here does not require restarting the server and is fully loaded dynamically. I have submitted the code to the src/test/resources/groovy directory, which can be tested directly.

1. Define the entity

 

@Entity(name = "TestContact")
class TestContact extends LongKeyEntity {
    String name
    String phone
}

A TestContact object is defined, the object includes two fields of contact name and phone, and inherits from LongKeyEntity, LongKeyEntity defines the id as a long value, and automatically increases 

 

 

2. Define Dao

 

@Repository
class TestContactDao extends BaseDao<TestContact> {

    @Autowired
    public TestContactDao(SessionFactory sessionFactory) {
        super(sessionFactory)
    }

    def list() {
        createCriteria().list()
    }

    @PostConstruct
    def createTableIfNecessary() {
        def session = sessionFactory().openStatelessSession()
        try {
            session.createSQLQuery("""
                CREATE TABLE IF NOT EXISTS `${TestContact.class.simpleName}`  (
                  `id` bigint(20) NOT NULL AUTO_INCREMENT,
                  `name` varchar(100) NOT NULL,
                  `phone` varchar(100) NOT NULL,
                  `createdTime` datetime NOT NULL,
                  `updatedTime` datetime NOT NULL,
                  `createdBy` varchar(100) NOT NULL,
                  `updatedBy` varchar(100) NOT NULL,
                  PRIMARY KEY (`id`)
                ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
            """).executeUpdate()
        } finally {
            session.close()
        }
    }
}

 Dao inherits from BaseDao and provides some basic operations, such as save an object and get an object by id, so only one list method is defined here to display all contacts. Since it is used for testing, the test data table is also created when the dao is created.

 

 

3. Define service

@Service
@Transactional
@Import([groovy.com.geo.aop.TestAspect.class, groovy.com.geo.config.TestResourceConfig.class])
class TestContactService extends BaseService<TestContact> {
    @Autowired
    public TestContactService(TestContactDao dao) {
        super (dao)
    }

}

 Define a service, which inherits from BaseService, which defines transactions for the methods of BaseDao.

Note that the service here does not define a method like the following

def list() {
    dao().list()
}

 Mainly because I use groovy's dynamic calling method, which is defined in BaseService, and will automatically call the corresponding method of dao, so there is no need to repeat the definition.

 

Another point to note is that the Import annotation is introduced here, so that the classloader can obtain the configuration information of TestAspect and TestResourceConfig and register it in the current applicationContext. TestAspect defines an AOP aspect, and TestResourceConfig is defined under this service. Configuration to be used, such as hibernate configuration, transaction manager configuration, and other resource definitions

@Configuration
@EnableAspectJAutoProxy
@Aspect
class TestAspect {
    def logger = LoggerFactory.getLogger(getClass())

    @Before('execution (* groovy.com.geo.service..*(..))')
    def before() {
        logger.info "i am invoked........."
    }
}

The AOP here defines methods to intercept all servcie classes under the groovy.com.geo.service package, and print a called message before calling these methods 

 

@Configuration
class TestResourceConfig extends BasicResourceConfig {

    @Override
    def Class<?>[] defineHibernateAnnotatedClasses() {
        return [TestContact.class]
    }

}

 BasicResourceConfig is inherited here, which defines a sessionFactory and a transaction manager. Here you just need to tell BasicResoureConfig to find which entity class to let hibernate know.

 

4. Define the controller

@RestController
@RequestMapping("/testContact")
class TestContactController {

    @Autowired
    TestContactService testService

    @RequestMapping(value = "/list", method = [RequestMethod.GET])
    def list() {
        testService.list()
    }

    @RequestMapping(value = "/save", method = [RequestMethod.POST])
    def save(@RequestBody TestContact updatedContact) {
        def currentUser = UserSession.CONTEXT().get()
        def oldContact = updatedContact
        if(updatedContact.id) {
            oldContact = testService.get(updatedContact.id)
            BeanUtils.copyProperties(updatedContact, oldContact, "createdBy", "createdTime", "updatedBy", "updatedTime")
        } else {
            oldContact.setCreatedBy(currentUser.username)
        }
        oldContact.setUpdatedBy(currentUser.username)
        testService.save(oldContact).toString()
    }

    @RequestMapping(value = "/delete/{id}", method = [RequestMethod.DELETE])
    def delete(@PathVariable("id") Long id) {
        def oldContact = testService.load(id)
        testService.delete(oldContact)
    }

}

 A contact controller is defined here, which provides CRUD operations. It should be noted here that a RequestMapping needs to be defined on the class for each controller, which is defined here as testContact, and then each operation needs to define the corresponding RequestMapping, so that the framework can be correct find the appropriate entry

 

5. Define the entry mapping



 Find the groovy file in the location shown in the figure, click to enter the mapping entry that defines the controller

class DynamicEntryMapping {
    public static final def map = [
            "testContact": "groovy.com.geo.web.TestContactController",
    ]
}

Define the controller class name corresponding to testContact so that the framework can locate the controller file

 

6. Configure Security

The framework uses spring security. Here you need to know a little about the web expression of spring security and configure the url security.



 Find DynamicSecurityMapping as shown in the figure, and then define security

class DynamicSecurityMapping {
    public static final def map = [
            "/**": "hasRole('ROLE_SUPER_ADMIN')",
    ]
}

 The above means that all requests require super administrator privileges

 

At this point, all business development is completed, only need to visit business-related pages, here is http://localhost:8080/test/contact.html

 

The whole process does not require you to restart the server, and each class can be dynamically added, deleted, or modified.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327064099&siteId=291194637