• 用Kotlin写一个基于Spring Boot的RESTful服务


    Spring太复杂了,配置这个东西简直就是浪费生命。尤其在没有什么并发压力,随便搞一个RESTful服务
    让整个业务跑起来先的情况下,更是么有必要纠结在一堆的XML配置上。显然这么想的人是很多的,于是就
    有了Spring Boot。又由于Java 8太墨迹于是有了Kotlin。

    数据源使用MySql。通过Spring Boot这个基本不怎么配置的,不怎么微的微框架的Spring Data JPA和Hibernate
    来访问数据。

    处理依赖

    这里使用Gradle来处理依赖。

    • 首先下载官网给的初始项目:
    git clone https://github.com/spring-guides/gs-accessing-data-jpa.git
    
    • 然后跳转到gs-accessing-data-jpa/initial目录下。
    • 用IntelliJ IDEA打开这个项目,选择使用Gradle管理依赖。

    之后Gradle会自动下载依赖项。这会花一点时间。你可以去和妹子聊一会儿了。。

    如果你觉得这样很麻烦的话,可以建立一个Gradle项目。之后根据上面的例子建立一个目录:

    └── src
        └── main
            └── java
                └── hello
    

    但是无论是用上面的哪种方式,最后都需要在Gradle文件中添加依赖项。这个Gradle文件是build.gradle。添加完依赖项
    之后是这样的:

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'idea'
    apply plugin: 'spring-boot'
    
    jar {
        baseName = 'gs-spring-boot'
        version = '0.1.0'
    }
    
    repositories {
        mavenCentral()
    }
    
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    dependencies {
        // tag::jetty[]
        compile("org.springframework.boot:spring-boot-starter-web") {
            exclude module: "spring-boot-starter-tomcat"
        }
        compile("org.springframework.boot:spring-boot-starter-jetty")
        // end::jetty[]
        // tag::actuator[]
        compile("org.springframework.boot:spring-boot-starter-actuator")
        // end::actuator[]
        compile('org.springframework.boot:spring-boot-starter-data-jpa:1.3.3.RELEASE')
    
        compile('mysql:mysql-connector-java:5.1.13')
    
        testCompile("junit:junit")
    }
    
    task wrapper(type: Wrapper) {
        gradleVersion = '2.3'
    }
    

    配置文件

    在目录src/main/resources/application.properties下编辑配置文件。默认是没有这个文件和相应的目录的,
    自行创建。

    spring.datasource.url = jdbc:mysql://localhost:3306/test
    spring.datasource.username = root
    spring.datasource.password = root
    #spring.datasource.driverClassName = com.mysql.jdbc.Driver
    
    # Specify the DBMS
    spring.jpa.database = MYSQL
    
    # Keep the connection alive if idle for a long time (needed in production)
    spring.datasource.testWhileIdle = true
    spring.datasource.validationQuery = SELECT 1
    
    # Show or not log for each sql query
    spring.jpa.show-sql = true
    
    # Hibernate ddl auto (create, create-drop, update)
    spring.jpa.hibernate.ddl-auto = update
    
    # Naming strategy
    spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
    
    # Use spring.jpa.properties.* for Hibernate native properties (the prefix is
    # stripped before adding them to the entity manager)
    
    # The SQL dialect makes Hibernate generate better SQL for the chosen database
    spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
    
    

    无需java的配置类,或者什么XML配置文件。

    使用配置项hibernate.ddl-auto = true,项目所需的数据库和相关表、列会自动根据定义的实体类创建。点击
    这里
    查看更多配置的说明。

    创建一个简单地实体类

    这里定义一个简单地实体类,并声明为JPA实体。这个类的文件存放在目录srcmainjavahelloEntities下。

    package hello.Entities
    
    import javax.validation.constraints.NotNull
    import java.io.Serializable;
    import javax.persistence.*;
    
    /**
     * Created by Bruce on 2016/3/9.
     */
    @Entity
    @Table(name = "user")
    data class User(@Id @GeneratedValue(strategy = GenerationType.AUTO) var id: Long? = 0,
                    @Column(nullable = false) var name: String? = null,
                    @Column(nullable = false) var email: String? = null) : Serializable {
    
        protected constructor() : this(id = null, name = null, email = null) {
        }
    }
    

    这里使用了Kotlin里的data class。data class最大的优点就是省去了定义getter和setter,以及toString()
    的时间。这些都已经默认实现。所以,在使用data class的对象的时候直接可以使用nameemail当然还有id这样的属性直接访问。

    无参数的构造函数是给JPA用的,所以访问级别设定为protected。主构造函数是用来创建和数据库操作相关的对象的。

    整个的整个类被@Entity修饰,说明整个类是一个JPA的实体类。@Table声明用来表明整个类对应的数据库表是哪一个。
    @Id修饰的User的属性id,会被JPA认为的对象的ID。同时@GeneratedValue(strategy = GenerationType.AUTO)
    的修饰说明这个ID是自动生成的。

    另外的两个属性nameemail@Column(nullable = false)修饰。说明两个列都是不可以为空的,同时说明两个列的名字
    和属性的名字是相同的。如果不同可以这样@Column(nullable = false, name="XXXXXX")

    创建简单地查询,或者说Dao类

    这个就更加的简单了。JPA会自动在运行时创建数据库需要的增删改查的实现。这个实现可以是根据我们给出的Repository
    来实现的。

    根据User类,我们来实现一个UserDao(Repository):

    package hello.Entities
    
    import org.springframework.data.repository.CrudRepository
    import org.springframework.transaction.annotation.Transactional
    
    @Transactional
    interface UserDao : CrudRepository<User, Long> {
        fun findByEmail(email: String): User?
    }
    

    泛型的类型参数分别是user和user的id的类型:User, Long。我们可以定义增删改查之外的Query。比如在上面的代码里
    我们定义了一个findByEmail()方法。具体的自定义查询时的命名规则可以查看这里

    用Controller测试一下

    数据库,Rest服务和书库的连接都已经搞定。那么,我们就来测试一下。

    我们在目录srcmainjavahelloControllers创建一个UserController类来测试和数据库的数据存取。

    package hello.Controllers
    
    import hello.Entities.User
    import hello.Entities.UserDao
    import org.springframework.beans.factory.annotation.Autowired
    import org.springframework.web.bind.annotation.RestController
    import org.springframework.web.bind.annotation.RequestMapping
    import org.springframework.web.bind.annotation.ResponseBody
    
    /**
     * Created by Bruce on 2016/3/9.
     */
    
    @RestController
    class UserController {
        @Autowired
        private var userDao: UserDao? = null
    
        @RequestMapping("/create")
        @ResponseBody
        public fun create(name: String, email: String): User? {
            try {
                var newUser = User(name = name, email = email)
                userDao?.save(newUser)
    
                return newUser
            } catch(e: Exception) {
                return null
            }
        }
    
        @RequestMapping("/delete")
        @ResponseBody
        public fun delete(id: Long): String {
            try {
                var user = User(id)
                userDao?.delete(user)
    
                return id.toString() + "deleted"
            } catch(e: Exception) {
                return "delete error " + e.message.toString()
            }
        }
    
        @RequestMapping("/get-by-email")
        @ResponseBody
        public fun getByEmail(email: String): User? {
            try {
                var user = userDao?.findByEmail(email)
                if (user != null) {
                    return user
                } else {
                    return null
                }
            } catch(e: Exception) {
                return null
            }
        }
    
        @RequestMapping("/update")
        @ResponseBody
        public fun updateUser(id: Long, name: String, email: String): User? {
            try {
                var user: User? = userDao?.findOne(id) ?: return null
    
                user?.name = name
                user?.email = email
                userDao?.save(user)
    
                return user
            } catch(e: Exception) {
                return null
            }
        }
    }
    

    测试URL可以是这样的:

    • /create?name=Jack&email=hello@234.com,使用指定的用户名和邮箱在数据库里生成一个新的user,id是自动生成的。
    • /delete?id=3, 删除id值为3的user。
    • /get-by-email?email=hello@234.com,注意Controller用到的UserDao.findByEmail()只返回一个user,所以如果有多个
      返回值的话会报错。
    • /update?id=1&email=what@123.com&name=Bruce,更新id为1的user。

    代码在这里

    参考文章:
    http://blog.netgloo.com/2014/10/27/using-mysql-in-spring-boot-via-spring-data-jpa-and-hibernate/
    https://spring.io/guides/gs/accessing-data-jpa/

  • 相关阅读:
    12-14面向对象--抽象基类、接口、委托
    关于 try catch catch
    C# using 三种使用方式
    互斥锁(Mutex)
    C#中Monitor类、Lock关键字和Mutex类
    System.Data.SQLite
    Dictionary<TKey, TValue> 类
    AttributeTargets 枚举
    C# is和as操作符
    合并委托(多路广播委托)
  • 原文地址:https://www.cnblogs.com/sunshine-anycall/p/5263511.html
Copyright © 2020-2023  润新知