用 Java 从零搭建一个可上线的网站(Spring Boot 实战)

用 Java 从零搭建一个可上线的网站(Spring Boot 实战)

很多人学 Java 学到能写接口、能连数据库,但真要“搭一个能跑起来的网站”时,反而卡在工程结构、路由、模板渲染、静态资源、部署这些细节上。本文用一个最小可用的方式,带你从零搭建一个可访问的站点:包含首页、文章列表页、文章详情页,并给出完整示例代码。你可以把它当成一个可扩展的骨架,后面再加登录、后台、缓存、搜索等功能。


一、技术选型与目标

我们用 Spring Boot + Thymeleaf + Maven 做一个传统网站(服务端渲染),优点是结构清晰、SEO友好、部署简单。

目标功能:

  • / 首页(欢迎页)
  • /posts 文章列表
  • /posts/{id} 文章详情
  • 静态资源:/css/site.css
  • 后续可轻松接 MySQL / Redis

二、创建 Spring Boot 项目依赖

pom.xml 关键依赖如下(核心是 web + thymeleaf):

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies>


三、项目目录结构(建议照抄)

src/main/java/com/example/demo
  ├── DemoApplication.java
  ├── controller
  │    └── SiteController.java
  ├── model
  │    └── Post.java
  └── repo
       └── PostRepository.java

src/main/resources ├── templates │ ├── index.html │ ├── posts.html │ └── post-detail.html └── static └── css └── site.css


四、数据模型:Post(文章实体)

Post.java

package com.example.demo.model;

import java.time.LocalDateTime;

public class Post { private Long id; private String title; private String content; private LocalDateTime createdAt;

public Post(Long id, String title, String content, LocalDateTime createdAt) {
    this.id = id;
    this.title = title;
    this.content = content;
    this.createdAt = createdAt;
}

public Long getId() { return id; }
public String getTitle() { return title; }
public String getContent() { return content; }
public LocalDateTime getCreatedAt() { return createdAt; }

}


五、模拟仓库:PostRepository(先不接数据库)

为了让网站立刻可跑,我们先用内存数据模拟:

PostRepository.java

package com.example.demo.repo;

import com.example.demo.model.Post; import org.springframework.stereotype.Repository;

import java.time.LocalDateTime; import java.util.*;

@Repository public class PostRepository { private final List<Post> posts = new ArrayList<>();

public PostRepository() {
    posts.add(new Post(1L, "Java 搭站第一步:结构与路由",
            "这篇文章介绍如何用 Spring Boot 做最小站点骨架。", LocalDateTime.now().minusDays(2)));
    posts.add(new Post(2L, "模板渲染:Thymeleaf 实战",
            "用 Thymeleaf 做列表页与详情页渲染,适合 SEO。", LocalDateTime.now().minusDays(1)));
    posts.add(new Post(3L, "部署上线:Jar + Nginx 反代",
            "把应用打包为 jar,配合 Nginx 反向代理上线。", LocalDateTime.now()));
}

public List<Post> findAll() {
    return Collections.unmodifiableList(posts);
}

public Optional<Post> findById(Long id) {
    return posts.stream().filter(p -> p.getId().equals(id)).findFirst();
}

}


六、控制器:SiteController(路由与页面渲染)

SiteController.java

package com.example.demo.controller;

import com.example.demo.repo.PostRepository; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*;

@Controller public class SiteController {

private final PostRepository repo;

public SiteController(PostRepository repo) {
    this.repo = repo;
}

@GetMapping("/")
public String index() {
    return "index";
}

@GetMapping("/posts")
public String posts(Model model) {
    model.addAttribute("posts", repo.findAll());
    return "posts";
}

@GetMapping("/posts/{id}")
public String postDetail(@PathVariable Long id, Model model) {
    var post = repo.findById(id).orElseThrow(() -> new IllegalArgumentException("Post not found"));
    model.addAttribute("post", post);
    return "post-detail";
}

}


七、页面模板:Thymeleaf 三个页面

templates/index.html

<html lang="zh">
<head>
  <meta charset="utf-8"/>
  <title>我的 Java 网站</title>
  <link rel="stylesheet" href="/css/site.css"/>
</head>
<body>
  <div class="container">
    <h1>Java 网站已启动 ✅</h1>
    <p>这是一个最小可用站点骨架:Spring Boot + Thymeleaf。</p>
    <a href="/posts">查看文章列表</a>
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

templates/posts.html

&lt;html lang="zh" xmlns:th="http://www.thymeleaf.org"&gt;
&lt;head&gt;
  &lt;meta charset="utf-8"/&gt;
  &lt;title&gt;文章列表&lt;/title&gt;
  &lt;link rel="stylesheet" href="/css/site.css"/&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class="container"&gt;
    &lt;h1&gt;文章列表&lt;/h1&gt;
    <ul>
      <li>
        <a></a>
        &lt;span class="meta" th:text="${#temporals.format(p.createdAt,'yyyy-MM-dd HH:mm')}"&gt;&lt;/span&gt;
      </li>
    </ul>
    <a href="/">返回首页</a>
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

templates/post-detail.html

&lt;html lang="zh" xmlns:th="http://www.thymeleaf.org"&gt;
&lt;head&gt;
  &lt;meta charset="utf-8"/&gt;
  &lt;title th:text="${post.title}"&gt;&lt;/title&gt;
  &lt;link rel="stylesheet" href="/css/site.css"/&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class="container"&gt;
    &lt;h1 th:text="${post.title}"&gt;&lt;/h1&gt;
    &lt;div class="meta" th:text="${#temporals.format(post.createdAt,'yyyy-MM-dd HH:mm')}"&gt;&lt;/div&gt;
    &lt;div class="content" th:text="${post.content}"&gt;&lt;/div&gt;
    <a href="/posts">返回列表</a>
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;


八、静态资源:简单 CSS

static/css/site.css

body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial; background:#f6f7fb; }
.container { max-width: 860px; margin: 40px auto; background:#fff; padding: 26px; border-radius: 14px; }
.btn { display:inline-block; padding:10px 14px; background:#111; color:#fff; text-decoration:none; border-radius:10px; }
.list { padding-left: 18px; }
.meta { color:#777; font-size: 12px; margin-left: 10px; }
.content { margin-top: 14px; line-height: 1.7; }
.link { display:inline-block; margin-top: 18px; color:#333; }


九、启动与访问

运行 DemoApplication.java 或命令:

mvn spring-boot:run

浏览器访问:

  • http://localhost:8080/
  • http://localhost:8080/posts
  • http://localhost:8080/posts/1


十、下一步:如何变成“真正可运营的网站”

这个骨架已经具备“网站形态”,后续你可以按优先级扩展:

  1. 接 MySQL:把 PostRepository 换成 JPA/Mapper
  2. 后台管理:加 /admin + 登录
  3. 缓存加速:Redis 缓存列表页
  4. SEO:站点地图、文章 URL 规范化
  5. 部署上线:Jar 后台运行 + Nginx 反代 + HTTPS

评论 0