分享 Rubyist 对比学习快速开发框架-SpringBoot

michael_roshen · 2016年06月21日 · 最后由 michael_roshen 回复于 2016年06月21日 · 4889 次阅读

Rails 框架首次提出是在 2004 年 7 月,它的研发者是 26 岁的丹麦人 David Heinemeier Hansson。不同于已有复杂的 Web 开发框架,Rails 是一个更符合实际需要而且更高效的 Web 开发框架。Rails 结合了 PHP 体系的优点(快速开发)和 Java 体系的优点(程序规整),因此,Rails 在其提出后不长的时间里就受到了业内广泛的关注。

SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Boot 致力于在蓬勃发展的快速应用开发领域。

构建工具

Rails: Rake SpringBoot:

$ brew install maven
$ brew install gradle
  • Maven 使用 xml 配置
  • Gradle 不是用 xml 配置

安装

Rails: gem install rails SpringBoot: SpringBoot 客户端使用 SpringBoot CLI

$ brew tap pivotal/tap
$ brew install springboot

创建项目

Rails: rails new blog SpringBoot:

$ spring init blog -d=web,data-jpa,h2,freemarker
$ cd foo
$ mvn dependency:resolve

参数说明:

  • blog 项目名称
  • -d 选择数据库
  • SpringBoot CLI 默认使用 Maven
  • 使用 Gradle 添加参数--build gradle
  • 查看更多使用 spring help init
  • web 使用 Spring MVC 框架和内置的 Tomcat
  • h2 内存数据库 (相当于 Rails 的 SQLite 数据库)
  • data-jpa 等同于 Rails 的 ActiveRecord,自动映射 model 和数据库
  • freemarker模版引擎
  • 使用spring init --list查看更多参数

启动服务器

Rails: rails s SpringBoot: 启动服务器,使用spring-boot:run, 这个命令又插件 Spring Maven/Gradle Plugin 插件提供

$ mvn spring-boot:run

打开浏览器查看http://localhost:8080/

Rails 脚手架

rails generate scaffold Post title content:string SpringBoot 没有代码生成功能,也不需要配置 xml

路由

Rails 在 routes.rb 中统一管理路由 SpringBoot

  • 没有统一管理路由的地方
  • 映射一个 URL 需要在类中设置:
    • 标注该类为控制器: @Controller
    • 标注公有方法为路由:@RequestMapping.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PagesController {
    @RequestMapping("/")
    public String home() {
        return "home";
    }
}
  • @Controller 注解告诉 Spring 检查这个类中的RequestMappings
  • @RequestMapping 声明一个 URL 的路由,请求方法,请求头,参数等信息。
resources :photos
@RequestMapping("/photos")
public class PhotosController {
    @RequestMapping(value = "/", method = RequestType.GET)
    public String listPhotos() { ... }

    @RequestMapping(value = "/new", method = RequestType.GET)
    public String newPhoto() { ... }

    @RequestMapping(value = "/", method = RequestType.POST)
    public String createPhoto() { ... }

    @RequestMapping(value = "/{photoId}", method = RequestType.GET)
    public String showPhoto(@PathVariable("photoId") Integer id, Model model) { ... }

    @RequestMapping(value = "/{photoId}/edit", method = RequestType.GET)
    public String editPhoto(@PathVariable("photoId") Integer id, Model model) { ... }

    @RequestMapping(value = "/{photoId}", method = RequestType.PUT)
    public String updatePhoto() { ... }

    @RequestMapping(value = "/", method = RequestType.DELETE)
    public String deletePhoto() { ... }
}

model 生成

rails g model Post title content:text

SpringBoot

  • 使用 SpringDataJPA
  • 使用@Entity注解这个类为实体类
@Entity(name = "categories")
public class Category {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private Long groupId;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "categoryId")
    @Where(clause = "enabled = 1")
    @OrderBy("name")
    private Set<Project> projects;
}

查询

Rails: Model.find, Modle.create, Model.update, Model.delete SpringBoot:

  • 需扩展 CrudRepository,从名字可以看出,这个接口已经内置了 CRUD 方法, 省去了自己拼写 sql 的麻烦,另外还可以根据需要添加查询方法,如下例子中 只需要定义方法,不需要写实现,CrudRepository 会自动完成,有点 Rails 元编程的意思。
public interface UserDao extends CrudRepository<User, Long> {
    public User findByEmail(String email);
}

复杂查询

Rails: Model.where().order().limit() SpringBoot:

  • 使用 SpringDataJPA,JPA 的写法有点奇葩,个人觉得 Rails 的链式查询 更易读更美观一些。
public interface CategoriesRepository
  extends CrudRepository<Category, Long> {
    List<Category> findAllByOrderByNameAsc();
}

关系映射

Rails: has_many :comments SpringBoot: SpringBoot 需要生成对应的 setter 和 getter 方法

@OneToMany(targetEntity=App.class, 
           mappedBy="user", 
           fetch=FetchType.EAGER, 
           cascade=CascadeType.ALL)
    private Set<App> apps;
    public Set<App> getApps() {
        return apps;
    }
    public void setApps(Set<App> apps) {
        this.apps= apps;
    }

开发环境

Rails: rails s -e (development, test & production) SpringBoot:

  • SpringBoot 本身没有提供各种开发环境的配置
  • 使用 SpringProfiles 插件来管理不同的环境
  • 为每个环境创建一个配置文件
    • application-development.propreties
    • application-test.propreties
    • application-production.propreties
  • 指定所使用的环境
    • mvn spring-boot:run -D spring.profiles.active=development

1)@RequestMapping 可省略 method = RequestType.GET

2)复杂查询可以用 querydsl

QCategory category = QCategory.category;
JPAQuery<?> queryFactory = new JPAQuery<Void>(entityManager);

List<Category> categories = queryFactory.selectFrom(category)
  .orderBy(category.name.asc())
  .fetch();

2)其实可以把所有的配置文件都写到一个里面,在启动的时候指定环境就行

environments:
    dev:
        url: http://dev.bar.com
        name: Developer Setup
    prod:
        url: http://foo.bar.com
        name: My Cool App
environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App
需要 登录 后方可回复, 如果你还没有账号请 注册新账号