So sánh Java Spring Boot sang Golang Iris Framework bằng một số đoạn code ngắn so sánh side-by-side bạn nắm bắt nhanh sự khác biệt và tương đồng.
1. Tạo một API cơ bản trả về “Hello, World!”
Java Spring Boot
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
@GetMapping("/hello")
public String sayHello() {
return "Hello, World!";
}
}
java
- Giải thích:
@SpringBootApplication
kết hợp cấu hình tự động, quét bean và khởi động ứng dụng.@RestController
đánh dấu lớp này xử lý REST API.@GetMapping("/hello")
ánh xạ yêu cầu GET tới/hello
.
Golang Iris Framework
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
app.Get("/hello", func(ctx iris.Context) {
ctx.Text("Hello, World!")
})
app.Listen(":8080")
}
go
- Giải thích:
- Iris sử dụng cách tiếp cận nhẹ nhàng hơn, không cần cấu hình phức tạp như Spring Boot.
app.Get
ánh xạ yêu cầu GET tới/hello
.ctx.Text
trả về chuỗi văn bản trực tiếp.
2. Xử lý tham số từ URL
Java Spring Boot
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user/{id}")
public String getUserById(@PathVariable Long id) {
return "User ID: " + id;
}
}
java
- Giải thích:
@PathVariable
trích xuất tham sốid
từ URL.
Golang Iris Framework
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
app.Get("/user/{id}", func(ctx iris.Context) {
id := ctx.Params().Get("id")
ctx.Text("User ID: " + id)
})
app.Listen(":8080")
}
go
- Giải thích:
{id}
là cú pháp định nghĩa tham số trong Iris.ctx.Params().Get("id")
lấy giá trị của tham số.
3. Xử lý JSON Request và Response
Java Spring Boot
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
static class User {
private String name;
// Getters và Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
@PostMapping("/user")
public User createUser(@RequestBody User user) {
return user; // Echo back the input
}
}
java
- Giải thích:
@RequestBody
ánh xạ dữ liệu JSON từ request vào đối tượngUser
.- Spring tự động serialize/deserialize JSON.
Golang Iris Framework
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
app.Post("/user", func(ctx iris.Context) {
type User struct {
Name string `json:"name"`
}
var user User
if err := ctx.ReadJSON(&user); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
return
}
ctx.JSON(user) // Echo back the input
})
app.Listen(":8080")
}
- Giải thích:
ctx.ReadJSON
đọc JSON từ request và ánh xạ vào structUser
.ctx.JSON
trả về phản hồi JSON.
4. Middleware (Xác thực cơ bản)
Java Spring Boot
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
@RestController
public class AuthController implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization");
if (token == null || !token.equals("secret")) {
response.setStatus(401);
return false;
}
return true;
}
@GetMapping("/secure")
public String secureEndpoint() {
return "Secure Data";
}
}
java
- Giải thích:
HandlerInterceptor
được dùng để chặn request và kiểm tra header.
Golang Iris Framework
package main
import "github.com/kataras/iris/v12"
func authMiddleware(ctx iris.Context) {
token := ctx.GetHeader("Authorization")
if token != "secret" {
ctx.StatusCode(iris.StatusUnauthorized)
return
}
ctx.Next()
}
func main() {
app := iris.New()
app.Use(authMiddleware)
app.Get("/secure", func(ctx iris.Context) {
ctx.Text("Secure Data")
})
app.Listen(":8080")
}
- Giải thích:
app.Use
đăng ký middleware toàn cục.ctx.Next()
chuyển tiếp request nếu hợp lệ.
5. Render một HTML page sử dụng View Template
Java Spring Boot
- Cấu hình: Dùng Thymeleaf làm template engine.
- File cấu hình (
application.properties
):
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
- Template (
src/main/resources/templates/hello.html
):
<!DOCTYPE html>
<html>
<head><title>Hello</title></head>
<body>
<h1>Hello, <span th:text="${name}"></span>!</h1>
</body>
</html>
- Controller:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TemplateController {
@GetMapping("/hello")
public String renderHello(Model model) {
model.addAttribute("name", "Spring User");
return "hello"; // Tên file template (hello.html)
}
}
- Giải thích:
@Controller
(khác@RestController
) cho phép render template.Model
truyền dữ liệu vào template.
Golang Iris Framework
- Template (
views/hello.html
):
<!DOCTYPE html>
<html>
<head><title>Hello</title></head>
<body>
<h1>Hello, {{.Name}}!</h1>
</body>
</html>
html
- Code:
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
app.RegisterView(iris.HTML("./views", ".html"))
app.Get("/hello", func(ctx iris.Context) {
ctx.ViewData("Name", "Iris User")
ctx.View("hello.html")
})
app.Listen(":8080")
}
- Giải thích:
RegisterView
đăng ký thư mục chứa template.ctx.ViewData
truyền dữ liệu,ctx.View
render file.
6. Upload file binary
Java Spring Boot
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@RestController
public class FileController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
return "Uploaded " + file.getOriginalFilename() + " (" + bytes.length + " bytes)";
}
return "No file uploaded";
}
}
java
- Giải thích:
@RequestParam("file")
nhận file từ form multipart.MultipartFile
cung cấp API để xử lý file.
Golang Iris Framework
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
app.Post("/upload", func(ctx iris.Context) {
file, info, err := ctx.FormFile("file")
if err != nil {
ctx.Text("No file uploaded")
return
}
defer file.Close()
ctx.Text("Uploaded " + info.Filename)
})
app.Listen(":8080")
}
go
- Giải thích:
ctx.FormFile
lấy file từ request multipart.info
chứa metadata như tên file.
7. Kết nối PostgreSQL, truy vấn bảng và render HTML
- Giả định: Có bảng
users(id, name)
trong PostgreSQL.
Java Spring Boot
- Cấu hình (
application.properties
):
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
- Entity (
User.java
):
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
private Long id;
private String name;
// Getters và Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
java
- Repository (
UserRepository.java
):
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
java
- Template (
src/main/resources/templates/users.html
):
<!DOCTYPE html>
<html>
<head><title>Users</title></head>
<body>
<h1>Users</h1>
<ul>
<li th:each="user : ${users}" th:text="${user.name}"></li>
</ul>
</body>
</html>
- Controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
@Autowired
private UserRepository userRepo;
@GetMapping("/users")
public String getUsers(Model model) {
model.addAttribute("users", userRepo.findAll());
return "users";
}
}
java
- Giải thích:
- Spring JPA tự động quản lý kết nối và truy vấn.
userRepo.findAll()
lấy toàn bộ dữ liệu từ bảngusers
.
Golang Iris Framework
- Dependency: Cần cài
go get -u github.com/lib/pq
. - Template (
views/users.html
):
<!DOCTYPE html>
<html>
<head><title>Users</title></head>
<body>
<h1>Users</h1>
<ul>
{{range .Users}}
<li>{{.Name}}</li>
{{end}}
</ul>
</body>
</html>
html
- Code:
package main
import (
"database/sql"
_ "github.com/lib/pq"
"github.com/kataras/iris/v12"
)
func main() {
app := iris.New()
app.RegisterView(iris.HTML("./views", ".html"))
db, _ := sql.Open("postgres", "postgres://postgres:password@localhost:5432/testdb?sslmode=disable")
defer db.Close()
app.Get("/users", func(ctx iris.Context) {
type User struct {
ID int
Name string
}
rows, _ := db.Query("SELECT id, name FROM users")
defer rows.Close()
var users []User
for rows.Next() {
var u User
rows.Scan(&u.ID, &u.Name)
users = append(users, u)
}
ctx.ViewData("Users", users)
ctx.View("users.html")
})
app.Listen(":8080")
}
go
- Giải thích:
sql.Open
thiết lập kết nối thủ công tới PostgreSQL.db.Query
thực hiện truy vấn, kết quả được quét vào sliceusers
.- Dữ liệu truyền vào template qua
ctx.ViewData
.
So sánh nhanh
Template:
- Spring Boot: Thymeleaf mạnh mẽ, tích hợp chặt với Java, nhưng cấu hình phức tạp hơn.
- Iris: Dùng Go template, đơn giản, nhẹ, nhưng ít tính năng hơn.
Upload file:
- Spring Boot:
MultipartFile
cung cấp API tiện lợi, phù hợp với hệ sinh thái lớn. - Iris:
FormFile
đơn giản, trực tiếp, phù hợp với phong cách tối giản của Go.
- Spring Boot:
Database:
- Spring Boot: JPA tự động hóa nhiều thứ (ORM), giảm code nhưng cần hiểu cấu hình.
- Iris: Yêu cầu viết SQL thủ công, kiểm soát tốt hơn nhưng mất công hơn.
Lời khuyên
- Thực hành: Tạo một dự án nhỏ với Iris (ví dụ: CRUD app) để làm quen với cách tổ chức code.
- Tài liệu: Xem thêm về Iris Views và Go PostgreSQL.
- Debug: Với Go, chú ý xử lý lỗi (error handling) cẩn thận vì không có try-catch như Java.
Bình luận