`
georgezeng
  • 浏览: 102468 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

手把手教会你开发动态web项目(3)

阅读更多

本章讲述如何进行业务开发,比如我们需要开发一个联系人的业务,显示联系人列表,增加联系人,修改联系人信息,删除联系人。此处所有的开发都不需要重启服务器,完全动态加载。我已经把代码提交到了src/test/resources/groovy目录下,可以直接进行测试。

1. 定义entity

 

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

定义了一个TestContact对象,对象包括联系人姓名和电话两个字段,并继承于LongKeyEntity,LongKeyEntity定义了id是long值,并自动增加 

 

 

2. 定义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继承于BaseDao,提供了一些最基本的操作,比如save一个对象,通过id获取一个对象,所以这里只定义了一个list方法,用来显示所有联系人。由于是测试使用,所以在创建该dao的同时也创建测试数据表。

 

 

3. 定义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)
    }

}

 定义一个service,继承于BaseService,BaseService是对BaseDao的方法进行事务定义。

注意,这里的service并没有定义一个类似下面的方法

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

 主要是因为我使用了groovy的动态调用方法,定义在了BaseService里,会自动去调用dao的相应的方法,所以不需要再重复定义了

 

还有一点注意,这里引入了Import的注解,目的是让classloader可以获取到TestAspect和TestResourceConfig的配置信息,并注册到当前的applicationContext中,TestAspect定义了一个AOP切面,TestResourceConfig则是定义了在这个service下需要使用的配置,比如hibernate的配置,事务管理器的配置,及其他资源的定义

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

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

这里的AOP定义了拦截所有groovy.com.geo.service包下的servcie类的方法,在调用这些方法前先打印一条被调用的信息 

 

@Configuration
class TestResourceConfig extends BasicResourceConfig {

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

}

 这里继承了BasicResourceConfig,它定义了一个sessionFactory和一个事务管理器。这里只需要告诉BasicResoureConfig去查找哪个entity类让hibernate知道即可。

 

4. 定义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)
    }

}

 这里定义了一个contact的controller,提供了CRUD操作,这里需要注意,需要为每个controller在类上定义一个RequestMapping,这里定义的是testContact,然后每个操作都需要定义对应的RequestMapping,这样框架才能正确找到相应的入口

 

5. 定义入口映射



 找到如图位置的groovy文件,点击进入定义controller的mapping入口

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

定义testContact对应的controller类名,目的是让框架可以定位到这个controller文件

 

6. 配置安全

框架使用spring security,这里需要你稍微了解一下spring security的web expression,对url进行安全配置



 如图找到DynamicSecurityMapping,然后定义安全

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

 上面的意思是所有的请求都需要有超级管理员的权限

 

至此,所有的业务开发完成,只需要访问业务相关的页面,这里访问的是http://localhost:8080/test/contact.html

 

整个过程不需要你重启服务器,每个类都可以进行动态的增删改

  • 大小: 21.5 KB
  • 大小: 20.9 KB
分享到:
评论

相关推荐

    手把手教会你无刷电机(赠送).zip

    【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...

    基于stm32的手把手教会你无刷电机(赠送).zip

    【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...

    第一章1节手把手教会无刷电机PCB.pptx

    【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...

    第一章4节手把手教会无刷电机1PCB.pptx

    【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...

    第一章6节手把手教会无刷电机1PCB.pptx

    【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...

    第一章5节手把手教会无刷电机1PCB.pptx

    【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、...

    web 2.0入门者 Ajax修炼之道-包含源码

    不仅教会你Ajax的技术细节,同时还带你了解各种功能强大的主流Ajax工具包(Dojo、Prototype、 Script.aculo.us、DWR、Backbase、SmartClient、Ajax.NET、SAJAX、JSON-RPC),掌握Ajax 实时查看源代码的方法以及进行...

    小白都能看得懂的教程 一本教你如何在前端实现富文本编辑器

    小白都能看得懂的教程 一本教你如何在前端实现富文本编辑...小白都能看懂的实战教程 手把手教你Python Web全栈开发 第二讲:[小白都能看懂的实战教程 手把手教你Python Web全栈开发 第二讲] 在前端实现富文本编辑器 这

    flask搭建.md

    由于flask属于轻量级web框架, 更加自由、灵活,可扩展性强,第三方库的选择面广,开发时可以结合自己最喜欢用的轮子,也能结合最流行最强大的Python库 。...以下手把手教会你如何搭建flask,及项目设计结构。

Global site tag (gtag.js) - Google Analytics