引言
在当今快速发展的软件开发领域,Java全栈工程师因其能够独立完成从后端服务到前端界面的完整开发流程而备受青睐。Java作为一门成熟、稳定且生态丰富的编程语言,为全栈开发提供了坚实的基础。本文将为有志于成为Java全栈工程师的开发者提供一条清晰的成长路线,涵盖从入门到精通的各个阶段,并详细讲解前后端核心技术栈的掌握方法。
第一阶段:Java基础入门(1-3个月)
1.1 Java语言核心基础
Java全栈工程师的起点必须是扎实的Java语言基础。这个阶段需要掌握:
- 基本语法:变量、数据类型、运算符、流程控制(if-else、for、while、switch)
- 面向对象编程:类与对象、封装、继承、多态、抽象类、接口
- 异常处理:try-catch-finally、自定义异常
- 集合框架:List、Set、Map及其常用实现类(ArrayList、HashSet、HashMap)
- IO流:字节流、字符流、缓冲流、对象序列化
示例代码:面向对象基础
// 定义一个动物基类
abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
// 抽象方法,子类必须实现
public abstract void makeSound();
// 具体方法
public void sleep() {
System.out.println(name + "正在睡觉...");
}
}
// 定义狗类,继承Animal
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + "说:汪汪汪!");
}
// 狗特有的方法
public void fetch() {
System.out.println(name + "正在捡球...");
}
}
// 测试类
public class AnimalTest {
public static void main(String[] args) {
Animal myDog = new Dog("旺财");
myDog.makeSound(); // 输出:旺财说:汪汪汪!
myDog.sleep(); // 输出:旺财正在睡觉...
// 多态演示
Animal[] animals = {
new Dog("大黄"),
new Dog("小黑")
};
for (Animal animal : animals) {
animal.makeSound();
}
}
}
1.2 开发环境搭建
- JDK安装:推荐使用JDK 11或17(LTS版本)
- IDE选择:IntelliJ IDEA(推荐)或Eclipse
- 构建工具:Maven或Gradle基础使用
- 版本控制:Git基础命令(clone、add、commit、push、pull)
1.3 基础项目实践
项目示例:控制台学生管理系统
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 学生类
class Student {
private String id;
private String name;
private int age;
private double score;
public Student(String id, String name, int age, double score) {
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}
// Getter和Setter方法
public String getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
public double getScore() { return score; }
@Override
public String toString() {
return String.format("学号:%s,姓名:%s,年龄:%d,成绩:%.1f",
id, name, age, score);
}
}
// 学生管理系统
class StudentManager {
private List<Student> students = new ArrayList<>();
private Scanner scanner = new Scanner(System.in);
public void run() {
while (true) {
System.out.println("\n=== 学生管理系统 ===");
System.out.println("1. 添加学生");
System.out.println("2. 查看所有学生");
System.out.println("3. 按学号查找学生");
System.out.println("4. 退出");
System.out.print("请选择操作:");
int choice = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
switch (choice) {
case 1:
addStudent();
break;
case 2:
showAllStudents();
break;
case 3:
findStudentById();
break;
case 4:
System.out.println("感谢使用,再见!");
return;
default:
System.out.println("无效选择,请重新输入!");
}
}
}
private void addStudent() {
System.out.print("请输入学号:");
String id = scanner.nextLine();
System.out.print("请输入姓名:");
String name = scanner.nextLine();
System.out.print("请输入年龄:");
int age = scanner.nextInt();
System.out.print("请输入成绩:");
double score = scanner.nextDouble();
scanner.nextLine();
Student student = new Student(id, name, age, score);
students.add(student);
System.out.println("学生添加成功!");
}
private void showAllStudents() {
if (students.isEmpty()) {
System.out.println("暂无学生信息!");
return;
}
System.out.println("\n所有学生信息:");
for (Student student : students) {
System.out.println(student);
}
}
private void findStudentById() {
System.out.print("请输入要查找的学号:");
String id = scanner.nextLine();
for (Student student : students) {
if (student.getId().equals(id)) {
System.out.println("找到学生:" + student);
return;
}
}
System.out.println("未找到学号为 " + id + " 的学生!");
}
}
// 主程序
public class StudentManagementSystem {
public static void main(String[] args) {
StudentManager manager = new StudentManager();
manager.run();
}
}
第二阶段:Java进阶与框架基础(3-6个月)
2.1 Java高级特性
- 多线程与并发:Thread类、Runnable接口、线程池(ExecutorService)、锁机制(synchronized、Lock)
- 反射机制:Class类、Constructor、Field、Method的使用
- 注解:自定义注解、元注解
- Lambda表达式与Stream API:函数式编程
- NIO:非阻塞IO、Selector、Buffer
示例代码:线程池与Lambda表达式
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 使用Lambda表达式创建任务
Runnable task1 = () -> {
System.out.println("任务1开始执行,线程:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1执行完毕");
};
Runnable task2 = () -> {
System.out.println("任务2开始执行,线程:" + Thread.currentThread().getName());
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务2执行完毕");
};
// 提交任务
executor.submit(task1);
executor.submit(task2);
// 使用Callable和Future获取返回值
Callable<String> callableTask = () -> {
Thread.sleep(2000);
return "任务3返回结果";
};
Future<String> future = executor.submit(callableTask);
try {
// 等待任务完成并获取结果
String result = future.get();
System.out.println("任务3结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
// 关闭线程池
executor.shutdown();
}
}
2.2 数据库基础
- SQL基础:CRUD操作、JOIN查询、子查询、聚合函数
- JDBC编程:连接数据库、执行SQL、处理结果集
- 数据库连接池:Druid、HikariCP
示例代码:JDBC操作MySQL
import java.sql.*;
public class JDBCDemo {
// 数据库连接信息
private static final String URL = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASSWORD = "password";
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 1. 加载驱动(JDBC 4.0+自动加载)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 建立连接
connection = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("数据库连接成功!");
// 3. 创建Statement
statement = connection.createStatement();
// 4. 执行查询
String sql = "SELECT * FROM users WHERE age > 18";
resultSet = statement.executeQuery(sql);
// 5. 处理结果集
System.out.println("查询结果:");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String email = resultSet.getString("email");
System.out.printf("ID: %d, 姓名: %s, 年龄: %d, 邮箱: %s%n",
id, name, age, email);
}
// 6. 插入数据(使用PreparedStatement防止SQL注入)
String insertSql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?)";
PreparedStatement pstmt = connection.prepareStatement(insertSql);
pstmt.setString(1, "张三");
pstmt.setInt(2, 25);
pstmt.setString(3, "zhangsan@example.com");
int rows = pstmt.executeUpdate();
System.out.println("插入了 " + rows + " 行数据");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 7. 关闭资源
try {
if (resultSet != null) resultSet.close();
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2.3 Web基础
- HTTP协议:请求方法、状态码、头部信息
- Servlet基础:Servlet生命周期、Request/Response对象
- JSP基础:JSP语法、EL表达式、JSTL标签
第三阶段:后端框架精通(6-12个月)
3.1 Spring Boot核心
Spring Boot是Java后端开发的事实标准,需要深入掌握:
- 自动配置原理:@SpringBootApplication、@Conditional注解
- 依赖注入:@Component、@Service、@Repository、@Controller
- 配置管理:application.properties/yml、Profile配置
- 数据访问:Spring Data JPA、MyBatis
- RESTful API开发:@RestController、@RequestMapping、@PathVariable、@RequestParam
示例代码:Spring Boot RESTful API
// 1. 实体类
@Entity
@Table(name = "products")
class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private BigDecimal price;
@Column
private String description;
// 构造函数、Getter/Setter省略
}
// 2. Repository接口
public interface ProductRepository extends JpaRepository<Product, Long> {
// 自定义查询方法
List<Product> findByNameContaining(String name);
List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
}
// 3. Service层
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public List<Product> getAllProducts() {
return productRepository.findAll();
}
public Product getProductById(Long id) {
return productRepository.findById(id)
.orElseThrow(() -> new RuntimeException("产品未找到"));
}
public Product createProduct(Product product) {
return productRepository.save(product);
}
public Product updateProduct(Long id, Product productDetails) {
Product product = getProductById(id);
product.setName(productDetails.getName());
product.setPrice(productDetails.getPrice());
product.setDescription(productDetails.getDescription());
return productRepository.save(product);
}
public void deleteProduct(Long id) {
productRepository.deleteById(id);
}
public List<Product> searchProducts(String keyword) {
return productRepository.findByNameContaining(keyword);
}
}
// 4. Controller层
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
// 获取所有产品
@GetMapping
public ResponseEntity<List<Product>> getAllProducts() {
List<Product> products = productService.getAllProducts();
return ResponseEntity.ok(products);
}
// 根据ID获取产品
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@PathVariable Long id) {
Product product = productService.getProductById(id);
return ResponseEntity.ok(product);
}
// 创建新产品
@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
Product createdProduct = productService.createProduct(product);
return ResponseEntity.status(HttpStatus.CREATED).body(createdProduct);
}
// 更新产品
@PutMapping("/{id}")
public ResponseEntity<Product> updateProduct(@PathVariable Long id,
@RequestBody Product product) {
Product updatedProduct = productService.updateProduct(id, product);
return ResponseEntity.ok(updatedProduct);
}
// 删除产品
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
return ResponseEntity.noContent().build();
}
// 搜索产品
@GetMapping("/search")
public ResponseEntity<List<Product>> searchProducts(@RequestParam String keyword) {
List<Product> products = productService.searchProducts(keyword);
return ResponseEntity.ok(products);
}
}
3.2 Spring Security
- 认证与授权:用户登录、角色权限控制
- JWT令牌:Token生成、验证、刷新
- OAuth2.0:第三方登录集成
示例代码:Spring Security + JWT
// 1. JWT工具类
@Component
public class JwtTokenUtil {
private static final String SECRET_KEY = "your-secret-key";
private static final long EXPIRATION_TIME = 86400000; // 24小时
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("roles", userDetails.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList()));
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
private Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
}
// 2. JWT认证过滤器
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
// 3. 安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
3.3 微服务架构
- Spring Cloud:Eureka、Ribbon、Feign、Hystrix、Zuul
- 服务注册与发现:Eureka Server/Client
- 配置中心:Spring Cloud Config
- API网关:Spring Cloud Gateway
- 分布式事务:Seata
第四阶段:前端技术栈(6-12个月)
4.1 HTML/CSS/JavaScript基础
- HTML5:语义化标签、表单、多媒体
- CSS3:Flexbox、Grid、动画、响应式设计
- JavaScript:ES6+特性(箭头函数、解构、Promise、async/await)、DOM操作
示例代码:现代JavaScript应用
// 1. ES6+ 特性示例
class ProductManager {
constructor() {
this.products = [];
}
// 箭头函数
addProduct = (product) => {
this.products.push(product);
return this.products.length;
}
// 解构赋值
getProductById(id) {
const product = this.products.find(p => p.id === id);
if (!product) {
throw new Error(`产品ID ${id} 未找到`);
}
return product;
}
// async/await 异步操作
async fetchProductsFromAPI() {
try {
const response = await fetch('https://api.example.com/products');
if (!response.ok) {
throw new Error(`HTTP错误! 状态码: ${response.status}`);
}
const data = await response.json();
this.products = data;
return data;
} catch (error) {
console.error('获取产品失败:', error);
throw error;
}
}
// Promise 示例
validateProduct(product) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (product.name && product.price > 0) {
resolve({ valid: true, message: '产品验证通过' });
} else {
reject({ valid: false, message: '产品信息不完整或价格无效' });
}
}, 1000);
});
}
}
// 2. DOM操作示例
function createProductCard(product) {
const card = document.createElement('div');
card.className = 'product-card';
card.innerHTML = `
<h3>${product.name}</h3>
<p class="price">¥${product.price}</p>
<p class="description">${product.description || '暂无描述'}</p>
<button class="btn-add" data-id="${product.id}">加入购物车</button>
`;
// 事件委托
card.addEventListener('click', (e) => {
if (e.target.classList.contains('btn-add')) {
const productId = e.target.dataset.id;
addToCart(productId);
}
});
return card;
}
// 3. 模块化示例
// productUtils.js
export const formatPrice = (price) => {
return `¥${price.toFixed(2)}`;
};
export const formatDate = (date) => {
return new Date(date).toLocaleDateString('zh-CN');
};
// main.js
import { formatPrice, formatDate } from './productUtils.js';
const product = {
name: '笔记本电脑',
price: 5999.99,
createdAt: new Date()
};
console.log(formatPrice(product.price)); // ¥5999.99
console.log(formatDate(product.createdAt)); // 2024/1/15
4.2 前端框架选择
Vue.js路线(推荐初学者):
- Vue 3:Composition API、响应式系统
- Vue Router:路由管理
- Vuex/Pinia:状态管理
- Element Plus:UI组件库
React路线(推荐有JavaScript基础者):
- React 18:Hooks、Context、Suspense
- React Router:路由管理
- Redux Toolkit:状态管理
- Ant Design:UI组件库
示例代码:Vue 3 Composition API
<!-- ProductList.vue -->
<template>
<div class="product-list">
<h2>产品列表</h2>
<!-- 搜索框 -->
<div class="search-box">
<input
v-model="searchKeyword"
placeholder="搜索产品..."
@input="debouncedSearch"
/>
<button @click="clearSearch">清除</button>
</div>
<!-- 产品列表 -->
<div v-if="loading" class="loading">加载中...</div>
<div v-else-if="error" class="error">{{ error }}</div>
<div v-else class="products-grid">
<ProductCard
v-for="product in filteredProducts"
:key="product.id"
:product="product"
@add-to-cart="handleAddToCart"
/>
</div>
<!-- 分页 -->
<div class="pagination" v-if="totalPages > 1">
<button
:disabled="currentPage === 1"
@click="changePage(currentPage - 1)"
>
上一页
</button>
<span>第 {{ currentPage }} / {{ totalPages }} 页</span>
<button
:disabled="currentPage === totalPages"
@click="changePage(currentPage + 1)"
>
下一页
</button>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { debounce } from 'lodash-es';
import ProductCard from './ProductCard.vue';
// 响应式状态
const products = ref([]);
const searchKeyword = ref('');
const currentPage = ref(1);
const pageSize = ref(12);
const loading = ref(false);
const error = ref(null);
// 计算属性
const filteredProducts = computed(() => {
if (!searchKeyword.value) return products.value;
return products.value.filter(product =>
product.name.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
product.description?.toLowerCase().includes(searchKeyword.value.toLowerCase())
);
});
const totalPages = computed(() => {
return Math.ceil(filteredProducts.value.length / pageSize.value);
});
const paginatedProducts = computed(() => {
const start = (currentPage.value - 1) * pageSize.value;
const end = start + pageSize.value;
return filteredProducts.value.slice(start, end);
});
// 方法
const fetchProducts = async () => {
loading.value = true;
error.value = null;
try {
const response = await fetch('/api/products');
if (!response.ok) throw new Error('获取产品失败');
products.value = await response.json();
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
const debouncedSearch = debounce(() => {
currentPage.value = 1; // 搜索时重置到第一页
}, 300);
const clearSearch = () => {
searchKeyword.value = '';
currentPage.value = 1;
};
const changePage = (page) => {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page;
}
};
const handleAddToCart = (productId) => {
// 调用Vuex/Pinia的action
console.log(`添加产品 ${productId} 到购物车`);
};
// 生命周期钩子
onMounted(() => {
fetchProducts();
});
// 监听器
watch(searchKeyword, (newVal, oldVal) => {
if (newVal !== oldVal) {
currentPage.value = 1;
}
});
</script>
<style scoped>
.product-list {
padding: 20px;
}
.search-box {
margin-bottom: 20px;
display: flex;
gap: 10px;
}
.search-box input {
flex: 1;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
}
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
.pagination {
margin-top: 30px;
display: flex;
justify-content: center;
align-items: center;
gap: 15px;
}
.loading, .error {
text-align: center;
padding: 40px;
font-size: 16px;
}
.error {
color: #f56c6c;
}
</style>
4.3 前端工程化
- 构建工具:Vite、Webpack
- 包管理:npm、yarn、pnpm
- TypeScript:类型系统、接口、泛型
- CSS预处理器:Sass/Less
- 测试框架:Jest、Vue Test Utils、React Testing Library
第五阶段:全栈整合与项目实战(12-18个月)
5.1 全栈项目架构设计
典型全栈项目结构:
my-fullstack-app/
├── backend/ # 后端项目
│ ├── src/main/java/com/example/app/
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 业务逻辑
│ │ ├── repository/ # 数据访问
│ │ ├── model/ # 实体类
│ │ ├── config/ # 配置类
│ │ └── security/ # 安全配置
│ ├── pom.xml # Maven配置
│ └── application.yml # 应用配置
│
├── frontend/ # 前端项目
│ ├── public/ # 静态资源
│ ├── src/
│ │ ├── components/ # 组件
│ │ ├── views/ # 页面
│ │ ├── store/ # 状态管理
│ │ ├── router/ # 路由
│ │ ├── api/ # API调用
│ │ ├── utils/ # 工具函数
│ │ └── App.vue # 根组件
│ ├── package.json
│ └── vite.config.js
│
├── docker/ # Docker配置
│ ├── backend.Dockerfile
│ ├── frontend.Dockerfile
│ └── docker-compose.yml
│
└── docs/ # 文档
5.2 完整项目示例:在线商城系统
后端实现(Spring Boot):
// 1. 用户模块
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody UserRegistrationDTO dto) {
try {
User user = userService.register(dto);
return ResponseEntity.ok(Map.of("message", "注册成功", "userId", user.getId()));
} catch (Exception e) {
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
}
}
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginDTO dto) {
try {
String token = userService.login(dto);
return ResponseEntity.ok(Map.of("token", token));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Map.of("error", e.getMessage()));
}
}
@GetMapping("/profile")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<UserProfileDTO> getProfile(@AuthenticationPrincipal UserDetails userDetails) {
UserProfileDTO profile = userService.getProfile(userDetails.getUsername());
return ResponseEntity.ok(profile);
}
}
// 2. 商品模块
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping
public ResponseEntity<Page<ProductDTO>> getProducts(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String category,
@RequestParam(required = false) String keyword) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
Page<ProductDTO> products = productService.getProducts(pageable, category, keyword);
return ResponseEntity.ok(products);
}
@GetMapping("/{id}")
public ResponseEntity<ProductDetailDTO> getProduct(@PathVariable Long id) {
ProductDetailDTO product = productService.getProductDetail(id);
return ResponseEntity.ok(product);
}
@PostMapping
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<ProductDTO> createProduct(@RequestBody ProductCreateDTO dto) {
ProductDTO product = productService.createProduct(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(product);
}
}
// 3. 订单模块
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
@PreAuthorize("hasRole('USER')")
public ResponseEntity<OrderDTO> createOrder(
@RequestBody OrderCreateDTO dto,
@AuthenticationPrincipal UserDetails userDetails) {
OrderDTO order = orderService.createOrder(dto, userDetails.getUsername());
return ResponseEntity.status(HttpStatus.CREATED).body(order);
}
@GetMapping("/my-orders")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<List<OrderDTO>> getMyOrders(
@AuthenticationPrincipal UserDetails userDetails) {
List<OrderDTO> orders = orderService.getUserOrders(userDetails.getUsername());
return ResponseEntity.ok(orders);
}
@PutMapping("/{orderId}/status")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<OrderDTO> updateOrderStatus(
@PathVariable Long orderId,
@RequestParam String status) {
OrderDTO order = orderService.updateOrderStatus(orderId, status);
return ResponseEntity.ok(order);
}
}
// 4. 购物车模块
@RestController
@RequestMapping("/api/cart")
public class CartController {
@Autowired
private CartService cartService;
@GetMapping
@PreAuthorize("hasRole('USER')")
public ResponseEntity<CartDTO> getCart(@AuthenticationPrincipal UserDetails userDetails) {
CartDTO cart = cartService.getCart(userDetails.getUsername());
return ResponseEntity.ok(cart);
}
@PostMapping("/items")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<CartDTO> addItemToCart(
@RequestBody CartItemDTO item,
@AuthenticationPrincipal UserDetails userDetails) {
CartDTO cart = cartService.addItem(userDetails.getUsername(), item);
return ResponseEntity.ok(cart);
}
@DeleteMapping("/items/{itemId}")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<CartDTO> removeItemFromCart(
@PathVariable Long itemId,
@AuthenticationPrincipal UserDetails userDetails) {
CartDTO cart = cartService.removeItem(userDetails.getUsername(), itemId);
return ResponseEntity.ok(cart);
}
@PutMapping("/items/{itemId}/quantity")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<CartDTO> updateItemQuantity(
@PathVariable Long itemId,
@RequestParam int quantity,
@AuthenticationPrincipal UserDetails userDetails) {
CartDTO cart = cartService.updateQuantity(userDetails.getUsername(), itemId, quantity);
return ResponseEntity.ok(cart);
}
}
// 5. 支付模块(集成第三方支付)
@RestController
@RequestMapping("/api/payments")
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping("/create")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<PaymentResponseDTO> createPayment(
@RequestBody PaymentRequestDTO request,
@AuthenticationPrincipal UserDetails userDetails) {
PaymentResponseDTO response = paymentService.createPayment(request, userDetails.getUsername());
return ResponseEntity.ok(response);
}
@PostMapping("/notify")
public ResponseEntity<?> paymentNotify(@RequestBody Map<String, Object> notifyData) {
// 处理支付平台的异步通知
paymentService.handlePaymentNotify(notifyData);
return ResponseEntity.ok().build();
}
@GetMapping("/history")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<List<PaymentHistoryDTO>> getPaymentHistory(
@AuthenticationPrincipal UserDetails userDetails) {
List<PaymentHistoryDTO> history = paymentService.getPaymentHistory(userDetails.getUsername());
return ResponseEntity.ok(history);
}
}
前端实现(Vue 3 + TypeScript):
// 1. API服务层
// src/services/api.ts
import axios, { AxiosInstance, AxiosResponse } from 'axios';
// 创建axios实例
const api: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
// 请求拦截器
api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 响应拦截器
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// Token过期或未认证
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
// 用户API
export const userApi = {
register: async (data: UserRegistrationData) => {
const response = await api.post('/users/register', data);
return response.data;
},
login: async (data: LoginData) => {
const response = await api.post('/users/login', data);
return response.data;
},
getProfile: async () => {
const response = await api.get('/users/profile');
return response.data;
}
};
// 产品API
export const productApi = {
getProducts: async (params: ProductSearchParams) => {
const response = await api.get('/products', { params });
return response.data;
},
getProduct: async (id: number) => {
const response = await api.get(`/products/${id}`);
return response.data;
},
createProduct: async (data: ProductCreateData) => {
const response = await api.post('/products', data);
return response.data;
}
};
// 订单API
export const orderApi = {
createOrder: async (data: OrderCreateData) => {
const response = await api.post('/orders', data);
return response.data;
},
getMyOrders: async () => {
const response = await api.get('/orders/my-orders');
return response.data;
}
};
// 购物车API
export const cartApi = {
getCart: async () => {
const response = await api.get('/cart');
return response.data;
},
addItem: async (item: CartItemData) => {
const response = await api.post('/cart/items', item);
return response.data;
},
removeItem: async (itemId: number) => {
const response = await api.delete(`/cart/items/${itemId}`);
return response.data;
},
updateQuantity: async (itemId: number, quantity: number) => {
const response = await api.put(`/cart/items/${itemId}/quantity`, null, {
params: { quantity }
});
return response.data;
}
};
// 2. 类型定义
// src/types/index.ts
export interface UserRegistrationData {
username: string;
email: string;
password: string;
confirmPassword: string;
}
export interface LoginData {
username: string;
password: string;
}
export interface UserProfile {
id: number;
username: string;
email: string;
roles: string[];
createdAt: string;
}
export interface Product {
id: number;
name: string;
price: number;
description?: string;
imageUrl?: string;
stock: number;
category: string;
createdAt: string;
}
export interface ProductSearchParams {
page?: number;
size?: number;
category?: string;
keyword?: string;
}
export interface CartItem {
id: number;
productId: number;
productName: string;
price: number;
quantity: number;
imageUrl?: string;
}
export interface Cart {
id: number;
items: CartItem[];
totalAmount: number;
itemCount: number;
}
export interface Order {
id: number;
orderNumber: string;
status: string;
totalAmount: number;
createdAt: string;
items: OrderItem[];
}
export interface OrderItem {
id: number;
productName: string;
price: number;
quantity: number;
}
// 3. Pinia状态管理
// src/stores/cartStore.ts
import { defineStore } from 'pinia';
import { cartApi } from '@/services/api';
import { Cart, CartItem } from '@/types';
export const useCartStore = defineStore('cart', {
state: (): Cart => ({
id: 0,
items: [],
totalAmount: 0,
itemCount: 0
}),
getters: {
// 计算总价
totalPrice: (state) => {
return state.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
},
// 计算总数量
totalItems: (state) => {
return state.items.reduce((sum, item) => sum + item.quantity, 0);
}
},
actions: {
async fetchCart() {
try {
const cart = await cartApi.getCart();
this.$patch(cart);
} catch (error) {
console.error('获取购物车失败:', error);
}
},
async addItem(productId: number, quantity: number = 1) {
try {
const cart = await cartApi.addItem({ productId, quantity });
this.$patch(cart);
return cart;
} catch (error) {
console.error('添加商品失败:', error);
throw error;
}
},
async removeItem(itemId: number) {
try {
const cart = await cartApi.removeItem(itemId);
this.$patch(cart);
return cart;
} catch (error) {
console.error('移除商品失败:', error);
throw error;
}
},
async updateQuantity(itemId: number, quantity: number) {
try {
const cart = await cartApi.updateQuantity(itemId, quantity);
this.$patch(cart);
return cart;
} catch (error) {
console.error('更新数量失败:', error);
throw error;
}
},
clearCart() {
this.$patch({
id: 0,
items: [],
totalAmount: 0,
itemCount: 0
});
}
}
});
// 4. 路由守卫
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import { useAuthStore } from '@/stores/authStore';
const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: { requiresAuth: false }
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
meta: { requiresAuth: false }
},
{
path: '/register',
name: 'Register',
component: () => import('@/views/Register.vue'),
meta: { requiresAuth: false }
},
{
path: '/products',
name: 'ProductList',
component: () => import('@/views/ProductList.vue'),
meta: { requiresAuth: false }
},
{
path: '/products/:id',
name: 'ProductDetail',
component: () => import('@/views/ProductDetail.vue'),
meta: { requiresAuth: false }
},
{
path: '/cart',
name: 'Cart',
component: () => import('@/views/Cart.vue'),
meta: { requiresAuth: true }
},
{
path: '/checkout',
name: 'Checkout',
component: () => import('@/views/Checkout.vue'),
meta: { requiresAuth: true }
},
{
path: '/orders',
name: 'OrderList',
component: () => import('@/views/OrderList.vue'),
meta: { requiresAuth: true }
},
{
path: '/admin',
name: 'AdminDashboard',
component: () => import('@/views/admin/Dashboard.vue'),
meta: { requiresAuth: true, requiresAdmin: true }
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
// 路由守卫
router.beforeEach((to, from, next) => {
const authStore = useAuthStore();
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const requiresAdmin = to.matched.some(record => record.meta.requiresAdmin);
// 检查是否需要认证
if (requiresAuth && !authStore.isAuthenticated) {
next({ name: 'Login', query: { redirect: to.fullPath } });
return;
}
// 检查是否需要管理员权限
if (requiresAdmin && !authStore.isAdmin) {
next({ name: 'Home' });
return;
}
next();
});
export default router;
// 5. 主应用组件
// src/App.vue
<template>
<div id="app">
<!-- 导航栏 -->
<nav class="navbar" v-if="!isLoginPage">
<div class="nav-container">
<router-link to="/" class="nav-brand">在线商城</router-link>
<div class="nav-links">
<router-link to="/products">产品</router-link>
<router-link to="/cart" class="cart-link">
购物车
<span v-if="cartStore.totalItems > 0" class="cart-badge">
{{ cartStore.totalItems }}
</span>
</router-link>
<router-link v-if="authStore.isAdmin" to="/admin">管理</router-link>
<div v-if="authStore.isAuthenticated" class="user-menu">
<span>{{ authStore.user?.username }}</span>
<button @click="logout">退出</button>
</div>
<div v-else class="auth-links">
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
</div>
</div>
</div>
</nav>
<!-- 主内容区 -->
<main class="main-content">
<router-view />
</main>
<!-- 全局通知 -->
<div v-if="notification" class="notification" :class="notification.type">
{{ notification.message }}
</div>
</div>
</template>
<script setup>
import { computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useAuthStore } from '@/stores/authStore';
import { useCartStore } from '@/stores/cartStore';
import { useNotificationStore } from '@/stores/notificationStore';
const route = useRoute();
const router = useRouter();
const authStore = useAuthStore();
const cartStore = useCartStore();
const notificationStore = useNotificationStore();
const isLoginPage = computed(() => route.path === '/login' || route.path === '/register');
const notification = computed(() => notificationStore.notification);
const logout = () => {
authStore.logout();
cartStore.clearCart();
router.push('/login');
};
onMounted(() => {
// 如果已登录,加载购物车
if (authStore.isAuthenticated) {
cartStore.fetchCart();
}
});
</script>
<style>
/* 全局样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background-color: #f5f5f5;
}
.navbar {
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 1000;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
}
.nav-brand {
font-size: 24px;
font-weight: bold;
color: #409eff;
text-decoration: none;
}
.nav-links {
display: flex;
gap: 20px;
align-items: center;
}
.nav-links a {
color: #333;
text-decoration: none;
padding: 8px 12px;
border-radius: 4px;
transition: all 0.3s;
}
.nav-links a:hover,
.nav-links a.router-link-active {
background: #409eff;
color: white;
}
.cart-link {
position: relative;
}
.cart-badge {
position: absolute;
top: -8px;
right: -8px;
background: #f56c6c;
color: white;
border-radius: 50%;
width: 20px;
height: 20px;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
}
.user-menu {
display: flex;
gap: 10px;
align-items: center;
}
.user-menu button {
background: #f56c6c;
color: white;
border: none;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
}
.auth-links {
display: flex;
gap: 10px;
}
.main-content {
max-width: 1200px;
margin: 20px auto;
padding: 0 20px;
min-height: calc(100vh - 100px);
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 12px 20px;
border-radius: 4px;
color: white;
z-index: 2000;
animation: slideIn 0.3s ease-out;
}
.notification.success {
background: #67c23a;
}
.notification.error {
background: #f56c6c;
}
.notification.warning {
background: #e6a23c;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
</style>
5.3 部署与运维
- Docker化:编写Dockerfile、docker-compose.yml
- CI/CD:GitHub Actions、Jenkins
- 监控:Spring Boot Actuator、Prometheus、Grafana
- 日志:ELK Stack(Elasticsearch、Logstash、Kibana)
示例:Docker配置
# backend.Dockerfile
FROM openjdk:17-jdk-slim as builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests
FROM openjdk:17-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
# frontend.Dockerfile
FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
# docker-compose.yml
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
depends_on:
- mysql
- redis
networks:
- app-network
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "80:80"
depends_on:
- backend
networks:
- app-network
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=mydb
volumes:
- mysql-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- app-network
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
networks:
- app-network
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- frontend
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
redis-data:
第六阶段:高级主题与持续学习(18个月以上)
6.1 性能优化
- JVM调优:GC算法、内存模型、性能监控工具(JVisualVM、JProfiler)
- 数据库优化:索引优化、查询优化、分库分表
- 缓存策略:Redis缓存、本地缓存(Caffeine)
- 异步处理:消息队列(RabbitMQ、Kafka)、异步任务
6.2 分布式系统
- 分布式锁:Redis分布式锁、ZooKeeper
- 分布式事务:Seata、Saga模式
- 服务治理:服务降级、熔断、限流
- 分布式追踪:SkyWalking、Zipkin
6.3 云原生技术
- 容器编排:Kubernetes基础
- 服务网格:Istio
- Serverless:AWS Lambda、阿里云函数计算
- 云服务:AWS、阿里云、腾讯云
6.4 安全与合规
- 安全编码:OWASP Top 10、SQL注入、XSS、CSRF
- 数据安全:加密算法、数据脱敏
- 合规要求:GDPR、等保2.0
6.5 软技能提升
- 代码质量:设计模式、重构技巧、代码审查
- 项目管理:敏捷开发、Scrum、Kanban
- 沟通协作:技术文档编写、技术分享、团队协作
学习资源推荐
在线课程
- Java基础:慕课网、极客时间《Java核心技术》
- Spring Boot:B站尚硅谷、黑马程序员
- 前端框架:Vue官方文档、React官方文档
书籍推荐
- Java:《Java核心技术》、《Effective Java》
- Spring:《Spring实战》、《Spring Boot实战》
- 前端:《JavaScript高级程序设计》、《Vue.js设计与实现》
实践平台
- GitHub:参与开源项目
- LeetCode:算法练习
- 牛客网:项目实战
总结
Java全栈工程师的成长是一个循序渐进的过程,需要扎实的基础、持续的学习和大量的实践。从Java语言基础到前后端框架,再到全栈整合和项目实战,每个阶段都需要投入足够的时间和精力。
关键建议:
- 不要急于求成:每个阶段都要打好基础,避免”空中楼阁”
- 多做项目:理论结合实践,通过项目巩固知识
- 持续学习:技术更新快,保持学习的热情
- 关注社区:参与技术社区,与同行交流
- 培养软技能:沟通、协作、解决问题的能力同样重要
记住,成为优秀的Java全栈工程师不仅需要掌握技术栈,更需要培养解决问题的思维和持续学习的能力。祝你在Java全栈开发的道路上取得成功!
