ToB企服应用市场:ToB评测及商务社交产业平台

标题: MJGA,让 Java 再次伟大,开箱即用 Spring Boot 怕不怕 Gin? [打印本页]

作者: 用户云卷云舒    时间: 2024-11-28 13:04
标题: MJGA,让 Java 再次伟大,开箱即用 Spring Boot 怕不怕 Gin?
泉源:juejin.cn/post/7245942451105562685
媒介

隔壁组的云盘算零零后女同事,后文简称 云女士 ,非说 Go 的 Gin 框架比 Springboot 更加的开箱即用,我心想在 Java 内里 Springboot 已经打遍天下无对手,这份秘闻岂是 Gin 能比。
但是云女士突出一个执拗,非我要 PK 一把, PK 内容就是她使用 Gin,而我使用 Springboot 快速搭建一个简单的 Crud 工程,最后让其他同事来评判哪个更开箱即用。我毫不犹豫就允许了,作为搭建 Springboot 学习工程的资深 Crud 选手,咱这份底气还是有的。
云女士选择使用 Gin + Gorm 来搭建,而我原本想选择 Springboot + MyBatis,后面转念一想,这 MyBatis 要写 XML 文件,指不定就由于这个被云女士嘲笑了,所以我把 MyBatis 替换为了 MyBatis-Plus,这就富足的简洁了吧。
正文

准备事项

既然是 Crud 工程,自然要准备好操作的表,我和云女士通过如下语句在各自的数据库中创建好了如下两张表。
  1. CREATE TABLE people (
  2.     id INT(11) PRIMARY KEY AUTO_INCREMENT,
  3.     p_name VARCHAR(255) NOT NULL,
  4.     p_age INT(11) NOT NULL
  5. )
  6. CREATE TABLE book (
  7.     id INT(11) PRIMARY KEY AUTO_INCREMENT,
  8.     b_name VARCHAR(255) NOT NULL,
  9.     b_price FLOAT NOT NULL
  10. )
复制代码
Gin快速搭建Crud工程

云女士的工程布局如下所示。

云女士的 go.mod 文件内容如下所示。
  1. module gobase
  2. go 1.17
  3. require (
  4.     github.com/gin-gonic/gin v1.6.0
  5.     github.com/jinzhu/gorm v1.9.16
  6.     github.com/sirupsen/logrus v1.9.3
  7.     github.com/spf13/cast v1.5.1
  8. )
复制代码
云女士定义了两个布局体作为模型( Model ),book.go 文件内容如下所示。
  1. package model
  2. const (
  3.     BookTableName = "book"
  4. )
  5. type Book struct {
  6.     ID int64 `gorm:"column:id"`
  7.     BookName string `gorm:"column:b_name"`
  8.     BookPrice float64 `gorm:"column:b_price"`
  9. }
  10. func (b *Book) TableName() string {
  11.     return BookTableName
  12. }
复制代码
people.go 文件内容如下所示。
  1. package model
  2. const (
  3.     PeopleTableName = "people"
  4. )
  5. type People struct {
  6.     ID int64 `gorm:"column:id"`
  7.     PeopleName string `gorm:"column:p_name"`
  8.     PeopleAge int64 `gorm:"column:p_age"`
  9. }
  10. func (p *People) TableName() string {
  11.     return PeopleTableName
  12. }
复制代码
云女士增补道,TableName()方法是为模型指定对应的表名。
云女士为 book 表和 people 表分别定义了 Dao 接口,dao.go 文件内容如下所示。
  1. package dao
  2. import "gobase/model"
  3. type BookDao interface {
  4.     AddBook(book *model.Book) error
  5.     UpdateBook(book *model.Book) error
  6.     DeleteBook(book *model.Book) error
  7.     ListBookById(id uint) (*model.Book, error)
  8. }
  9. type PeopleDao interface {
  10.     AddPeople(book *model.People) error
  11.     UpdatePeople(book *model.People) error
  12.     DeletePeople(book *model.People) error
  13.     ListPeopleById(id uint) (*model.People, error)
  14. }
复制代码
BookDao 接口对应的实现在book_dao_impl.go文件中,实现如下。
  1. package dao
  2. import (
  3.     "github.com/jinzhu/gorm"
  4.     "gobase/model"
  5. )
  6. type BookDaoImpl struct {
  7.     DB *gorm.DB
  8. }
  9. func (b *BookDaoImpl) AddBook(book *model.Book) error {
  10.     if createResult := b.DB.Create(book); createResult.Error != nil {
  11.         return createResult.Error
  12.     }
  13.     return nil
  14. }
  15. func (b *BookDaoImpl) UpdateBook(book *model.Book) error {
  16.     if saveResult := b.DB.Save(book); saveResult.Error != nil {
  17.         return saveResult.Error
  18.     }
  19.     return nil
  20. }
  21. func (b *BookDaoImpl) DeleteBook(book *model.Book) error {
  22.     if deleteResult := b.DB.Delete(book); deleteResult.Error != nil {
  23.         return deleteResult.Error
  24.     }
  25.     return nil
  26. }
  27. func (b *BookDaoImpl) ListBookById(id uint) (*model.Book, error) {
  28.     var book model.Book
  29.     if listResult := b.DB.Where("id = ?", id).First(&book); listResult.Error != nil {
  30.         return nil, listResult.Error
  31.     }
  32.     return &book, nil
  33. }
复制代码
PeopleDao 接口对应的实现在people_dao_impl.go文件中,实现如下。
  1. package dao
  2. import (
  3.     "github.com/jinzhu/gorm"
  4.     "gobase/model"
  5. )
  6. type PeopleDaoImpl struct {
  7.     DB *gorm.DB
  8. }
  9. func (b *PeopleDaoImpl) AddPeople(people *model.People) error {
  10.     if createResult := b.DB.Create(people); createResult.Error != nil {
  11.         return createResult.Error
  12.     }
  13.     return nil
  14. }
  15. func (b *PeopleDaoImpl) UpdatePeople(people *model.People) error {
  16.     if saveResult := b.DB.Save(people); saveResult.Error != nil {
  17.         return saveResult.Error
  18.     }
  19.     return nil
  20. }
  21. func (b *PeopleDaoImpl) DeletePeople(people *model.People) error {
  22.     if deleteResult := b.DB.Delete(people); deleteResult.Error != nil {
  23.         return deleteResult.Error
  24.     }
  25.     return nil
  26. }
  27. func (b *PeopleDaoImpl) ListPeopleById(id uint) (*model.People, error) {
  28.     var people model.People
  29.     if listResult := b.DB.Where("id = ?", id).First(&people); listResult.Error != nil {
  30.         return nil, listResult.Error
  31.     }
  32.     return &people, nil
  33. }
复制代码
要操作数据库,肯定需要数据库毗连,云女士将数据库毗连的管理实现在了mysql_connection_pool.go文件中,内容如下所示。
  1. package mysql
  2. import (
  3.     "fmt"
  4.     "github.com/jinzhu/gorm"
  5.     "gobase/dao"
  6.     "log"
  7.     "time"
  8. )
  9. const (
  10.     UserName     = "root"
  11.     PassWord     = "root"
  12.     Host         = "192.168.101.8"
  13.     Port         = 3306
  14.     Database     = "gotest"
  15.     MaxLifetime  = 60 * time.Second
  16.     MaxIdletime  = 30 * time.Second
  17.     MaxOpenconns = 6
  18.     MaxIdleconns = 2
  19.     Dialect      = "mysql"
  20. )
  21. type DataSouce struct {
  22.     db      *gorm.DB
  23. }
  24. func NewDataSource() *DataSouce {
  25.     var db *gorm.DB
  26.     dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Asia%%2FShanghai",
  27.             UserName, PassWord, Host, Port, Database)
  28.     db, err := gorm.Open(Dialect, dsn)
  29.     if err != nil {
  30.         log.Fatal(err.Error())
  31.     }
  32.     db.DB().SetConnMaxLifetime(MaxLifetime)
  33.     db.DB().SetConnMaxIdleTime(MaxIdletime)
  34.     db.DB().SetMaxOpenConns(MaxOpenconns)
  35.     db.DB().SetMaxOpenConns(MaxIdleconns)
  36.     return &DataSouce{
  37.         db: db,
  38.     }
  39. }
  40. // BookDao 操作book表
  41. func (d *DataSouce) BookDao() dao.BookDao {
  42.     return &dao.BookDaoImpl{
  43.         DB: d.db,
  44.     }
  45. }
  46. // PeopleDao 操作people表
  47. func (d *DataSouce) PeopleDao() dao.PeopleDao {
  48.     return &dao.PeopleDaoImpl{
  49.         DB: d.db,
  50.     }
  51. }
复制代码
云女士将路由写在了webservice.go文件中,内容如下。
  1. package adapter
  2. import (
  3.     "github.com/gin-gonic/gin"
  4.     "gobase/mysql"
  5. )
  6. func Init() error {
  7.     dataSouce := mysql.NewDataSource()
  8.     bookController := NewBookController(dataSouce)
  9.     propleController := NewPropleController(dataSouce)
  10.     engine := gin.Default()
  11.     routerGroupBook := engine.Group("/book")
  12.     routerGroupBook.POST("/add", bookController.AddBook)
  13.     routerGroupBook.POST("/update", bookController.UpdateBook)
  14.     routerGroupBook.POST("/delete", bookController.DeleteBook)
  15.     routerGroupBook.POST("/list", bookController.ListBookById)
  16.     routerGroupPeople := engine.Group("/people")
  17.     routerGroupPeople.POST("/add", propleController.AddPeople)
  18.     routerGroupPeople.POST("/update", propleController.UpdatePeople)
  19.     routerGroupPeople.POST("/delete", propleController.DeletePeople)
  20.     routerGroupPeople.POST("/list", propleController.ListPeopleById)
  21.     return engine.Run()
  22. }
复制代码
其实除了绑定路由,云女士还在Init()函数中进行了简单的服务注入,也就是创建数据库毗连池,然后将数据库毗连池给到对应的 web 服务。
云女士将操作 book 表对应的 web 服务写在了book_controller.go文件中,其实现如下所示。
  1. package adapter
  2. import (
  3.     "github.com/gin-gonic/gin"
  4.     "github.com/sirupsen/logrus"
  5.     "github.com/spf13/cast"
  6.     "gobase/model"
  7.     "gobase/mysql"
  8.     "net/http"
  9. )
  10. type BookController struct {
  11.     dataSource *mysql.DataSouce
  12. }
  13. func NewBookController(dataSource *mysql.DataSouce) BookController {
  14.     return BookController{
  15.         dataSource: dataSource,
  16.     }
  17. }
  18. func (b *BookController) AddBook(ctx *gin.Context) {
  19.     var book model.Book
  20.     if err := ctx.ShouldBind(&book); err != nil {
  21.         logrus.Error("读取Book信息失败")
  22.         ctx.JSON(http.StatusInternalServerError, gin.H{
  23.             "message": "failed",
  24.         })
  25.         return
  26.     }
  27.     bookDao := b.dataSource.BookDao()
  28.     err := bookDao.AddBook(&book)
  29.     if err != nil {
  30.         logrus.Error("添加Book失败", err)
  31.         ctx.JSON(http.StatusInternalServerError, gin.H{
  32.             "message": "failed",
  33.         })
  34.         return
  35.     }
  36.     ctx.JSON(http.StatusOK, gin.H{
  37.         "message": "success",
  38.     })
  39. }
  40. func (b *BookController) UpdateBook(ctx *gin.Context) {
  41.     var book model.Book
  42.     if err := ctx.ShouldBind(&book); err != nil {
  43.         logrus.Error("读取Book信息失败")
  44.         ctx.JSON(http.StatusInternalServerError, gin.H{
  45.             "message": "failed",
  46.         })
  47.         return
  48.     }
  49.     bookDao := b.dataSource.BookDao()
  50.     err := bookDao.UpdateBook(&book)
  51.     if err != nil {
  52.         logrus.Error("更新Book失败", err)
  53.         ctx.JSON(http.StatusInternalServerError, gin.H{
  54.             "message": "failed",
  55.         })
  56.         return
  57.     }
  58.     ctx.JSON(http.StatusOK, gin.H{
  59.         "message": "success",
  60.     })
  61. }
  62. func (b *BookController) DeleteBook(ctx *gin.Context) {
  63.     var book model.Book
  64.     if err := ctx.ShouldBind(&book); err != nil {
  65.         logrus.Error("读取Book信息失败")
  66.         ctx.JSON(http.StatusInternalServerError, gin.H{
  67.             "message": "failed",
  68.         })
  69.         return
  70.     }
  71.     bookDao := b.dataSource.BookDao()
  72.     err := bookDao.DeleteBook(&book)
  73.     if err != nil {
  74.         logrus.Error("删除Book失败", err)
  75.         ctx.JSON(http.StatusInternalServerError, gin.H{
  76.             "message": "failed",
  77.         })
  78.         return
  79.     }
  80.     ctx.JSON(http.StatusOK, gin.H{
  81.         "message": "success",
  82.     })
  83. }
  84. func (b *BookController) ListBookById(ctx *gin.Context) {
  85.     id := cast.ToUint(ctx.Query("id"))
  86.     bookDao := b.dataSource.BookDao()
  87.     book, err := bookDao.ListBookById(id)
  88.     if err != nil {
  89.         logrus.Error("查询Book失败", err)
  90.         ctx.JSON(http.StatusInternalServerError, gin.H{
  91.             "message": "failed",
  92.         })
  93.         return
  94.     }
  95.     ctx.JSON(http.StatusOK, book)
  96. }
复制代码
云女士将操作 people 表对应的 web 服务写在了people_controller.go文件中,其实现如下所示。
  1. package adapter
  2. import (
  3.     "github.com/gin-gonic/gin"
  4.     "github.com/sirupsen/logrus"
  5.     "github.com/spf13/cast"
  6.     "gobase/model"
  7.     "gobase/mysql"
  8.     "net/http"
  9. )
  10. type PeopleController struct {
  11.     dataSource *mysql.DataSouce
  12. }
  13. func NewPropleController(dataSource *mysql.DataSouce) PeopleController {
  14.     return PeopleController{
  15.         dataSource: dataSource,
  16.     }
  17. }
  18. func (p *PeopleController) AddPeople(ctx *gin.Context) {
  19.     var people model.People
  20.     if err := ctx.ShouldBind(&people); err != nil {
  21.         logrus.Error("读取People信息失败")
  22.         ctx.JSON(http.StatusInternalServerError, gin.H{
  23.             "message": "failed",
  24.         })
  25.         return
  26.     }
  27.     peopleDao := p.dataSource.PeopleDao()
  28.     err := peopleDao.AddPeople(&people)
  29.     if err != nil {
  30.         logrus.Error("添加People失败", err)
  31.         ctx.JSON(http.StatusInternalServerError, gin.H{
  32.             "message": "failed",
  33.         })
  34.         return
  35.     }
  36.     ctx.JSON(http.StatusOK, gin.H{
  37.         "message": "success",
  38.     })
  39. }
  40. func (p *PeopleController) UpdatePeople(ctx *gin.Context) {
  41.     var people model.People
  42.     if err := ctx.ShouldBind(&people); err != nil {
  43.         logrus.Error("读取People信息失败")
  44.         ctx.JSON(http.StatusInternalServerError, gin.H{
  45.             "message": "failed",
  46.         })
  47.         return
  48.     }
  49.     peopleDao := p.dataSource.PeopleDao()
  50.     err := peopleDao.UpdatePeople(&people)
  51.     if err != nil {
  52.         logrus.Error("更新People失败", err)
  53.         ctx.JSON(http.StatusInternalServerError, gin.H{
  54.             "message": "failed",
  55.         })
  56.         return
  57.     }
  58.     ctx.JSON(http.StatusOK, gin.H{
  59.         "message": "success",
  60.     })
  61. }
  62. func (p *PeopleController) DeletePeople(ctx *gin.Context) {
  63.     var people model.People
  64.     if err := ctx.ShouldBind(&people); err != nil {
  65.         logrus.Error("读取People信息失败")
  66.         ctx.JSON(http.StatusInternalServerError, gin.H{
  67.             "message": "failed",
  68.         })
  69.         return
  70.     }
  71.     peopleDao := p.dataSource.PeopleDao()
  72.     err := peopleDao.DeletePeople(&people)
  73.     if err != nil {
  74.         logrus.Error("删除People失败", err)
  75.         ctx.JSON(http.StatusInternalServerError, gin.H{
  76.             "message": "failed",
  77.         })
  78.         return
  79.     }
  80.     ctx.JSON(http.StatusOK, gin.H{
  81.         "message": "success",
  82.     })
  83. }
  84. func (p *PeopleController) ListPeopleById(ctx *gin.Context) {
  85.     id := cast.ToUint(ctx.Query("id"))
  86.     peopleDao := p.dataSource.PeopleDao()
  87.     people, err := peopleDao.ListPeopleById(id)
  88.     if err != nil {
  89.         logrus.Error("查询People失败", err)
  90.         ctx.JSON(http.StatusInternalServerError, gin.H{
  91.             "message": "failed",
  92.         })
  93.         return
  94.     }
  95.     ctx.JSON(http.StatusOK, people)
  96. }
复制代码
最后,云女士简单的展示了一下对 book 表和 prople 表的 Crud 操作。
book 表和 people 表的增删改成功时返回内容如下所示。

book 表和 people 表的查询成功时返回内容如下所示。


Spring boot 快速搭建Crud工程

Spring Boot 基础就不介绍了,推荐看这个实战项目:
https://github.com/javastacks/spring-boot-best-practice
云女士基于 Gin 和 Gorm 搭建的 Crud 工程,我看完后内心扑哧一笑:不外如此。
那现在该轮到我表演了。首先给出整个工程布局图如下所示。

POM 文件内容如下所示。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5.     <modelVersion>4.0.0</modelVersion>
  6.     <parent>
  7.         <groupId>org.springframework.boot</groupId>
  8.         <artifactId>spring-boot-starter-parent</artifactId>
  9.         <version>2.4.1</version>
  10.     </parent>
  11.     <groupId>com.lee.javabase</groupId>
  12.     <artifactId>javabase</artifactId>
  13.     <version>1.0-SNAPSHOT</version>
  14.     <dependencies>
  15.         <dependency>
  16.             <groupId>org.springframework.boot</groupId>
  17.             <artifactId>spring-boot-starter-web</artifactId>
  18.         </dependency>
  19.         <dependency>
  20.             <groupId>org.springframework.boot</groupId>
  21.             <artifactId>spring-boot-starter-jdbc</artifactId>
  22.         </dependency>
  23.         <dependency>
  24.             <groupId>com.baomidou</groupId>
  25.             <artifactId>mybatis-plus-boot-starter</artifactId>
  26.             <version>3.1.0</version>
  27.         </dependency>
  28.         <dependency>
  29.             <groupId>mysql</groupId>
  30.             <artifactId>mysql-connector-java</artifactId>
  31.             <version>8.0.16</version>
  32.         </dependency>
  33.         <dependency>
  34.             <groupId>org.projectlombok</groupId>
  35.             <artifactId>lombok</artifactId>
  36.         </dependency>
  37.     </dependencies>
  38. </project>
复制代码
同样,定义 book 表和 people 表对应的实体类 Book 和 People,如下所示。
  1. @Getter
  2. @Setter
  3. public class Book {
  4.     @TableField("id")
  5.     private int id;
  6.     @TableField("b_name")
  7.     private String bookName;
  8.     @TableField("b_price")
  9.     private float bookPrice;
  10. }
  11. @Getter
  12. @Setter
  13. public class People {
  14.     @TableField("id")
  15.     private int id;
  16.     @TableField("p_name")
  17.     private String peopleName;
  18.     @TableField("p_age")
  19.     private int peopleAge;
  20. }
复制代码
然后定义定义接口,如下所示。
  1. @Mapper
  2. public interface BookMapper extends BaseMapper<Book> {
  3. }
  4. @Mapper
  5. public interface PeopleMapper extends BaseMapper<People> {
  6. }
复制代码
最后是对应的 Controller 实现, BookController 实现如下。
  1. @Slf4j
  2. @RestController
  3. @RequestMapping("/book")
  4. public class BookController {
  5.     @Autowired
  6.     private BookMapper bookMapper;
  7.     @PostMapping("/add")
  8.     public ResponseEntity<String> addBook(@RequestBody Book book) {
  9.         try {
  10.             bookMapper.insert(book);
  11.             return new ResponseEntity<>("添加图书成功", HttpStatus.OK);
  12.         } catch (Exception e) {
  13.             log.error("添加图书失败", e);
  14.             return new ResponseEntity<>("添加图书失败", HttpStatus.INTERNAL_SERVER_ERROR);
  15.         }
  16.     }
  17.     @PostMapping("/update")
  18.     public ResponseEntity<String> updateBook(@RequestBody Book book) {
  19.         try {
  20.             bookMapper.updateById(book);
  21.             return new ResponseEntity<>("更新图书成功", HttpStatus.OK);
  22.         } catch (Exception e) {
  23.             log.error("更新图书失败", e);
  24.             return new ResponseEntity<>("更新图书失败", HttpStatus.INTERNAL_SERVER_ERROR);
  25.         }
  26.     }
  27.     @PostMapping("/delete")
  28.     public ResponseEntity<String> deleteBook(@RequestParam("id") int id) {
  29.         try {
  30.             bookMapper.deleteById(id);
  31.             return new ResponseEntity<>("删除图书成功", HttpStatus.OK);
  32.         } catch (Exception e) {
  33.             log.error("删除图书失败", e);
  34.             return new ResponseEntity<>("删除图书失败", HttpStatus.INTERNAL_SERVER_ERROR);
  35.         }
  36.     }
  37.     @PostMapping("/list")
  38.     public ResponseEntity<Book> listBook(@RequestParam("id") int id) {
  39.         try {
  40.             Book book = bookMapper.selectById(id);
  41.             return new ResponseEntity<>(book, HttpStatus.OK);
  42.         } catch (Exception e) {
  43.             log.error("查询图书失败", e);
  44.             return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
  45.         }
  46.     }
  47. }
复制代码
PeopleController 实现如下所示。
  1. @Slf4j
  2. @RestController
  3. @RequestMapping("/people")
  4. public class PeopleController {
  5.     @Autowired
  6.     private PeopleMapper peopleMapper;
  7.     @PostMapping("/add")
  8.     public ResponseEntity<String> addPeople(@RequestBody People people) {
  9.         try {
  10.             peopleMapper.insert(people);
  11.             return new ResponseEntity<>("添加人物成功", HttpStatus.OK);
  12.         } catch (Exception e) {
  13.             log.error("添加人物失败", e);
  14.             return new ResponseEntity<>("添加人物失败", HttpStatus.INTERNAL_SERVER_ERROR);
  15.         }
  16.     }
  17.     @PostMapping("/update")
  18.     public ResponseEntity<String> updatePeople(@RequestBody People people) {
  19.         try {
  20.             peopleMapper.updateById(people);
  21.             return new ResponseEntity<>("更新人物成功", HttpStatus.OK);
  22.         } catch (Exception e) {
  23.             log.error("更新人物失败", e);
  24.             return new ResponseEntity<>("更新人物失败", HttpStatus.INTERNAL_SERVER_ERROR);
  25.         }
  26.     }
  27.     @PostMapping("/delete")
  28.     public ResponseEntity<String> deletePeople(@RequestParam("id") int id) {
  29.         try {
  30.             peopleMapper.deleteById(id);
  31.             return new ResponseEntity<>("删除人物成功", HttpStatus.OK);
  32.         } catch (Exception e) {
  33.             log.error("删除人物失败", e);
  34.             return new ResponseEntity<>("删除人物失败", HttpStatus.INTERNAL_SERVER_ERROR);
  35.         }
  36.     }
  37.     @PostMapping("/list")
  38.     public ResponseEntity<People> listPeople(@RequestParam("id") int id) {
  39.         try {
  40.             People people = peopleMapper.selectById(id);
  41.             return new ResponseEntity<>(people, HttpStatus.OK);
  42.         } catch (Exception e) {
  43.             log.error("查询人物失败", e);
  44.             return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
  45.         }
  46.     }
  47. }
复制代码
启动应用步伐, book 表的 Crud 操作效果如下所示。

prople 表的 Crud 操作效果如下所示。

总结

我公布,Springboot 就是快速搭建 Crud 工程的神。
其实,在基于 Gin 和 Gorm 搭建 Crud 工程时,云女士还是写得复杂了一点,但是我有幸看过她们云平台的项目的代码,云女士写得也没毛病,虽然是个简化版,但也是严酷服从她们项目的代码布局来实现的。
说回 Springboot,毫无疑问,无论是天然自带 Tomcat 或 Jetty ,还是和三方框架整合的各种 Starter 包,Springboot 都将开箱即用做到了极致,但是转念又一想,其实 Springboot 和 Gin 严酷来说做比力没啥意义,就像 Java 和 Go 的比力一样,我觉得也没啥意义,各自的优势区间不一样,而且各自也都在相关的领域叱咤风云。
各位看官,你们觉得呢。
更多文章推荐:
1.Spring Boot 3.x 教程,太全了!
2.2,000+ 道 Java面试题及答案整理(2024最新版)
3.免费获取 IDEA 激活码的 7 种方式(2024最新版)
觉得不错,别忘了随手点赞+转发哦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4