深入解析:从 .NET 到 Java 的转型指南:详细学习路线与实践建议

在这里插入图片描述

文章目录

在这里插入图片描述

第一部分:转型背景与核心差异分析

1.1 为什么需要从 .NET 转型到 Java

在当前的技术环境中,从 .NET 转型到 Java 通常基于以下考虑:

  1. 跨平台需求增加:Java 的"一次编写,到处运行"特性在云原生和容器化环境中具有优势
  2. 生态系统丰富性:Java 拥有庞大的开源生态系统和社区支持
  3. 成本考量:Java 开源技术栈可以降低许可成本
  4. 人才市场因素:Java 开发者在全球范围内更为普及
  5. 企业级应用成熟度:Java 在企业级应用和大规模系统中有着深厚的积累

1.2 .NET 与 Java 核心架构差异

1.2.1 运行时环境对比

.NET CLR vs JVM

// .NET 中的类型系统示例
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public virtual void Display()
{
Console.WriteLine($"Name: {Name}, Age: {Age}");
}
}
// Java 中的对应实现
public class Person {
private String name;
private int age;
public Person() {}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public void display() {
System.out.println("Name: " + name + ", Age: " + age);
}
}

主要差异

  • Java 中没有属性语法,使用 getter/setter 方法
  • Java 方法默认是虚方法(virtual),而 C# 需要显式声明
  • Java 包机制与 .NET 命名空间有相似性但实现不同
1.2.2 内存管理机制

.NET GC vs Java GC

// .NET 中的资源管理
public class ResourceHandler : IDisposable
{
private bool disposed = false;
public void ProcessData()
{
if (disposed)
throw new ObjectDisposedException(nameof(ResourceHandler));
// 处理逻辑
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// 释放托管资源
}
// 释放非托管资源
disposed = true;
}
}
~ResourceHandler()
{
Dispose(false);
}
}
// Java 中的资源管理
public class ResourceHandler implements AutoCloseable {
private boolean closed = false;
public void processData() {
if (closed) {
throw new IllegalStateException("ResourceHandler is closed");
}
// 处理逻辑
}
@Override
public void close() {
if (!closed) {
// 释放资源
closed = true;
}
}
// Java 7+ 的 try-with-resources
public static void main(String[] args) {
try (ResourceHandler handler = new ResourceHandler()) {
handler.processData();
} catch (Exception e) {
e.printStackTrace();
}
}
}

1.3 心态调整与学习策略

1.3.1 相似性利用
  • 面向对象编程概念相通
  • 设计模式应用基本一致
  • 软件开发原则通用
1.3.2 差异性重视
  • 平台特性差异
  • 生态系统工具链
  • 部署和运维方式

第二部分:Java 语言基础深入学习

2.1 Java 语法核心概念

2.1.1 基本数据类型与包装类
// Java 基本数据类型与包装类
public class DataTypesExample {
public static void main(String[] args) {
// 基本数据类型
byte byteValue = 127;
short shortValue = 32767;
int intValue = 2147483647;
long longValue = 9223372036854775807L; // 注意 L 后缀
float floatValue = 3.14f; // 注意 f 后缀
double doubleValue = 3.141592653589793;
char charValue = 'A';
boolean booleanValue = true;
// 对应的包装类
Byte byteObj = byteValue;
Short shortObj = shortValue;
Integer intObj = intValue;
Long longObj = longValue;
Float floatObj = floatValue;
Double doubleObj = doubleValue;
Character charObj = charValue;
Boolean booleanObj = booleanValue;
// 自动装箱和拆箱
Integer autoBoxed = 100; // 自动装箱
int autoUnboxed = autoBoxed; // 自动拆箱
// 与 .NET 对比:Java 有明确的原始类型和包装类型区分
}
}
2.1.2 字符串处理
public class StringHandling {
public static void main(String[] args) {
// 字符串创建
String str1 = "Hello";
String str2 = new String("World");
// 字符串不可变性
String original = "Java";
String modified = original.concat(" Programming");
System.out.println(original); // 输出: Java
System.out.println(modified); // 输出: Java Programming
// StringBuilder 用于可变字符串操作
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString();
System.out.println(result); // 输出: Hello World
// StringBuffer 线程安全版本
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("Thread");
stringBuffer.append("Safe");
// 与 C# 对比:Java 字符串也是不可变的,但 Java 有 StringBuilder/StringBuffer
}
}

2.2 面向对象编程深入

2.2.1 类与继承
// 基类
public abstract class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// 抽象方法
public abstract void makeSound();
// 具体方法
public void sleep() {
System.out.println(name + " is sleeping");
}
// final 方法,不能被子类重写
public final void breathe() {
System.out.println(name + " is breathing");
}
}
// 接口
public interface Pet {
void play();
String getOwner();
}
// 继承与实现
public class Dog extends Animal implements Pet {
private String owner;
public Dog(String name, int age, String owner) {
super(name, age); // 调用父类构造函数
this.owner = owner;
}
@Override
public void makeSound() {
System.out.println("Woof! Woof!");
}
@Override
public void play() {
System.out.println(name + " is playing with " + owner);
}
@Override
public String getOwner() {
return owner;
}
// 静态方法
public static void describe() {
System.out.println("Dogs are loyal animals");
}
}
2.2.2 访问控制与封装
public class AccessModifiersExample {
// private - 仅当前类可见
private String privateField = "private";
// default (package-private) - 同包可见
String defaultField = "default";
// protected - 同包和子类可见
protected String protectedField = "protected";
// public - 所有类可见
public String publicField = "public";
// getter 和 setter 方法
public String getPrivateField() {
return privateField;
}
public void setPrivateField(String value) {
this.privateField = value;
}
}

2.3 异常处理机制

public class ExceptionHandling {
// 检查型异常
public void readFile(String filename) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.err.println("File not found: " + filename);
throw e; // 重新抛出异常
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
throw e;
} finally {
// 确保资源被释放
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
System.err.println("Error closing reader: " + e.getMessage());
}
}
}
}
// 使用 try-with-resources (Java 7+)
public void readFileModern(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} // 自动调用 reader.close()
}
// 非检查型异常
public void divideNumbers(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Divisor cannot be zero");
}
int result = a / b;
System.out.println("Result: " + result);
}
// 自定义异常
public static class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
public CustomException(String message, Throwable cause) {
super(message, cause);
}
}
}

2.4 集合框架

import java.util.*;
import java.util.stream.Collectors;
public class CollectionExamples {
public void listExamples() {
// ArrayList - 类似 C# List<T>
List<String> arrayList = new ArrayList<>();
  arrayList.add("Apple");
  arrayList.add("Banana");
  arrayList.add("Orange");
  // LinkedList
  List<String> linkedList = new LinkedList<>();
    linkedList.add("First");
    linkedList.add("Second");
    // 遍历方式
    for (String fruit : arrayList) {
    System.out.println(fruit);
    }
    // 使用迭代器
    Iterator<String> iterator = arrayList.iterator();
      while (iterator.hasNext()) {
      System.out.println(iterator.next());
      }
      // Java 8+ Stream API
      arrayList.stream()
      .filter(f -> f.startsWith("A"))
      .forEach(System.out::println);
      }
      public void setExamples() {
      // HashSet - 无序,不允许重复
      Set<String> hashSet = new HashSet<>();
        hashSet.add("Apple");
        hashSet.add("Banana");
        hashSet.add("Apple"); // 不会被添加
        // TreeSet - 有序
        Set<String> treeSet = new TreeSet<>();
          treeSet.add("Orange");
          treeSet.add("Apple");
          treeSet.add("Banana");
          // 输出顺序: Apple, Banana, Orange
          }
          public void mapExamples() {
          // HashMap - 类似 C# Dictionary<TKey, TValue>
            Map<String, Integer> hashMap = new HashMap<>();
              hashMap.put("John", 25);
              hashMap.put("Jane", 30);
              hashMap.put("Bob", 35);
              // 获取值
              Integer age = hashMap.get("John");
              // 遍历
              for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
                System.out.println(entry.getKey() + ": " + entry.getValue());
                }
                // Java 8+ 方式
                hashMap.forEach((key, value) -> System.out.println(key + ": " + value));
                // TreeMap - 按键排序
                Map<String, Integer> treeMap = new TreeMap<>();
                  treeMap.put("Orange", 5);
                  treeMap.put("Apple", 3);
                  treeMap.put("Banana", 7);
                  // 按键顺序: Apple, Banana, Orange
                  }
                  public void streamExamples() {
                  List<String> names = Arrays.asList("John", "Jane", "Bob", "Alice", "Charlie");
                    // Stream 操作
                    List<String> result = names.stream()
                      .filter(name -> name.length() > 4)
                      .map(String::toUpperCase)
                      .sorted()
                      .collect(Collectors.toList());
                      System.out.println(result); // [ALICE, CHARLIE]
                      // 分组
                      Map<Integer, List<String>> groupedByLength = names.stream()
                        .collect(Collectors.groupingBy(String::length));
                        System.out.println(groupedByLength);
                        }
                        }

第三部分:Java 生态系统与工具链

3.1 构建工具:Maven 与 Gradle

3.1.1 Maven 详细配置
<!-- pom.xml 示例 -->
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
  <!-- 项目坐标 -->
  <groupId>com.example</groupId>
  <artifactId>my-java-app</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>
    <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>5.3.9</spring.version>
    </properties>
    <dependencies>
      <!-- Spring Framework -->
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
        </dependency>
        <!-- 测试依赖 -->
          <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13.2</version>
          <scope>test</scope>
          </dependency>
          <!-- 日志 -->
            <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.32</version>
            </dependency>
          </dependencies>
          <build>
            <plugins>
              <!-- 编译器插件 -->
                <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                  <configuration>
                  <source>11</source>
                  <target>11</target>
                  </configuration>
                </plugin>
                <!-- 打包插件 -->
                  <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-jar-plugin</artifactId>
                  <version>3.2.0</version>
                    <configuration>
                      <archive>
                        <manifest>
                        <mainClass>com.example.MainApplication</mainClass>
                        </manifest>
                      </archive>
                    </configuration>
                  </plugin>
                </plugins>
              </build>
            </project>
3.1.2 Gradle 构建脚本
// build.gradle 示例
plugins {
id 'java'
id 'application'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework:spring-context:5.3.9'
implementation 'org.slf4j:slf4j-api:1.7.32'
testImplementation 'junit:junit:4.13.2'
}
application {
mainClassName = 'com.example.MainApplication'
}
// 自定义任务
task createStartScripts(type: CreateStartScripts) {
mainClass = 'com.example.MainApplication'
applicationName = 'myapp'
outputDir = new File(project.buildDir, 'scripts')
classpath = jar.outputs.files + project.configurations.runtimeClasspath
}
// 测试配置
test {
useJUnit()
testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
}
}

3.2 开发工具与环境配置

3.2.1 IDE 选择与配置

IntelliJ IDEA 推荐配置

  • 安装 Lombok 插件
  • 配置 Code Style 符合团队规范
  • 启用 Annotation Processors
  • 配置 Debug 和 Hot Swap

Eclipse 配置

  • 安装 Spring Tools Suite
  • 配置 Build Path
  • 设置 Formatter 和 Clean Up
3.2.2 版本控制集成
// Git 版本控制最佳实践示例
public class VersionControlExample {
/**
* 功能:用户注册
* 作者:张三
* 日期:2023-10-01
* 版本:1.0
*/
public void registerUser(String username, String password) {
// 参数验证
if (username == null || username.trim().isEmpty()) {
throw new IllegalArgumentException("用户名不能为空");
}
if (password == null || password.length() < 6) {
throw new IllegalArgumentException("密码长度至少6位");
}
// 业务逻辑
// ...
}
/**
* 功能:用户登录
* 修改:李四 - 2023-10-02 - 添加记住登录状态功能
*/
public boolean loginUser(String username, String password, boolean rememberMe) {
// 登录逻辑
return true;
}
}

3.3 测试框架

3.3.1 JUnit 测试
import org.junit.*;
import static org.junit.Assert.*;
public class CalculatorTest {
private Calculator calculator;
@BeforeClass
public static void setUpClass() {
// 在所有测试方法之前执行一次
System.out.println("测试类初始化");
}
@AfterClass
public static void tearDownClass() {
// 在所有测试方法之后执行一次
System.out.println("测试类清理");
}
@Before
public void setUp() {
// 在每个测试方法之前执行
calculator = new Calculator();
}
@After
public void tearDown() {
// 在每个测试方法之后执行
calculator = null;
}
@Test
public void testAdd() {
// 准备
int a = 5;
int b = 3;
int expected = 8;
// 执行
int actual = calculator.add(a, b);
// 验证
assertEquals("加法计算错误", expected, actual);
}
@Test
public void testDivide() {
// 测试正常除法
assertEquals(2, calculator.divide(6, 3));
}
@Test(expected = IllegalArgumentException.class)
public void testDivideByZero() {
// 测试除零异常
calculator.divide(5, 0);
}
@Test
@Ignore("尚未实现")
public void testAdvancedFeature() {
// 被忽略的测试
}
// 参数化测试
@RunWith(Parameterized.class)
public static class ParameterizedTest {
private int input;
private int expected;
private Calculator calculator = new Calculator();
public ParameterizedTest(int input, int expected) {
this.input = input;
this.expected = expected;
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
  return Arrays.asList(new Object[][] {
  {0, 0}, {1, 1}, {2, 4}, {3, 9}
  });
  }
  @Test
  public void testSquare() {
  assertEquals(expected, calculator.square(input));
  }
  }
  }
  // 被测试的类
  class Calculator {
  public int add(int a, int b) {
  return a + b;
  }
  public int divide(int a, int b) {
  if (b == 0) {
  throw new IllegalArgumentException("除数不能为零");
  }
  return a / b;
  }
  public int square(int x) {
  return x * x;
  }
  }
3.3.2 Mockito 模拟测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private EmailService emailService;
@InjectMocks
private UserService userService;
@Test
public void testRegisterUser() {
// 准备模拟数据
User user = new User("john@example.com", "John Doe");
when(userRepository.save(any(User.class))).thenReturn(user);
doNothing().when(emailService).sendWelcomeEmail(anyString());
// 执行测试
User registeredUser = userService.registerUser("john@example.com", "John Doe");
// 验证行为
verify(userRepository, times(1)).save(any(User.class));
verify(emailService, times(1)).sendWelcomeEmail("john@example.com");
// 验证结果
assertNotNull(registeredUser);
assertEquals("john@example.com", registeredUser.getEmail());
}
@Test
public void testRegisterUserWithExistingEmail() {
// 模拟已存在的用户
when(userRepository.findByEmail("existing@example.com"))
.thenReturn(new User("existing@example.com", "Existing User"));
// 验证异常
try {
userService.registerUser("existing@example.com", "New User");
fail("应该抛出异常");
} catch (IllegalArgumentException e) {
assertEquals("邮箱已存在", e.getMessage());
}
// 验证保存方法没有被调用
verify(userRepository, never()).save(any(User.class));
}
@Captor
private ArgumentCaptor<User> userCaptor;
  @Test
  public void testUserRegistrationDetails() {
  // 执行测试
  userService.registerUser("test@example.com", "Test User");
  // 捕获参数并验证
  verify(userRepository).save(userCaptor.capture());
  User capturedUser = userCaptor.getValue();
  assertEquals("test@example.com", capturedUser.getEmail());
  assertEquals("Test User", capturedUser.getName());
  assertNotNull(capturedUser.getRegistrationDate());
  }
  }
  // 相关类定义
  class User {
  private String email;
  private String name;
  private Date registrationDate;
  public User(String email, String name) {
  this.email = email;
  this.name = name;
  this.registrationDate = new Date();
  }
  // getters and setters
  }
  interface UserRepository {
  User save(User user);
  User findByEmail(String email);
  }
  interface EmailService {
  void sendWelcomeEmail(String email);
  }
  class UserService {
  private UserRepository userRepository;
  private EmailService emailService;
  public User registerUser(String email, String name) {
  // 检查邮箱是否已存在
  User existing = userRepository.findByEmail(email);
  if (existing != null) {
  throw new IllegalArgumentException("邮箱已存在");
  }
  // 创建新用户
  User newUser = new User(email, name);
  User savedUser = userRepository.save(newUser);
  // 发送欢迎邮件
  emailService.sendWelcomeEmail(email);
  return savedUser;
  }
  }

第四部分:Spring 框架深入学习

4.1 Spring Core 核心概念

4.1.1 依赖注入与控制反转
// 配置类方式
@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:application.properties")
public class AppConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:data.sql")
.build();
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 服务类
@Service
@Transactional
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
// 构造器注入(推荐)
@Autowired
public UserService(UserRepository userRepository, EmailService emailService) {
this.userRepository = userRepository;
this.emailService = emailService;
}
public User registerUser(UserRegistrationDto dto) {
// 业务逻辑
User user = new User();
user.setEmail(dto.getEmail());
user.setName(dto.getName());
user.setPassword(encodePassword(dto.getPassword()));
User savedUser = userRepository.save(user);
emailService.sendWelcomeEmail(savedUser.getEmail());
return savedUser;
}
private String encodePassword(String password) {
// 密码加密逻辑
return password; // 实际应该使用 BCrypt 等
}
}
// 数据访问层
@Repository
public class JpaUserRepository implements UserRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public User save(User user) {
if (user.getId() == null) {
entityManager.persist(user);
return user;
} else {
return entityManager.merge(user);
}
}
@Override
public Optional<User> findByEmail(String email) {
  TypedQuery<User> query = entityManager.createQuery(
    "SELECT u FROM User u WHERE u.email = :email", User.class);
    query.setParameter("email", email);
    try {
    return Optional.of(query.getSingleResult());
    } catch (NoResultException e) {
    return Optional.empty();
    }
    }
    }
    // 邮件服务
    @Service
    public class EmailService {
    private final JavaMailSender mailSender;
    private final TemplateEngine templateEngine;
    @Autowired
    public EmailService(JavaMailSender mailSender, TemplateEngine templateEngine) {
    this.mailSender = mailSender;
    this.templateEngine = templateEngine;
    }
    @Async
    public void sendWelcomeEmail(String email) {
    try {
    MimeMessage message = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    helper.setTo(email);
    helper.setSubject("欢迎注册");
    Context context = new Context();
    context.setVariable("email", email);
    String htmlContent = templateEngine.process("welcome-email", context);
    helper.setText(htmlContent, true);
    mailSender.send(message);
    } catch (Exception e) {
    throw new RuntimeException("发送邮件失败", e);
    }
    }
    }
4.1.2 AOP 面向切面编程
// 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}
// 切面类
@Aspect
@Component
public class LoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
logger.info("{} executed in {} ms",
joinPoint.getSignature(), executionTime);
return proceed;
}
// 异常处理切面
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))",
throwing = "ex")
public void logServiceException(Exception ex) {
logger.error("Service layer exception: {}", ex.getMessage(), ex);
}
// 方法调用前后通知
@Before("execution(* com.example.service.UserService.*(..))")
public void logMethodCall(JoinPoint joinPoint) {
logger.debug("调用方法: {} with args: {}",
joinPoint.getSignature().getName(),
Arrays.toString(joinPoint.getArgs()));
}
}
// 使用切面的服务
@Service
public class OrderService {
@LogExecutionTime
public Order createOrder(OrderRequest request) {
// 业务逻辑
try {
Thread.sleep(100); // 模拟处理时间
return new Order();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
}

4.2 Spring Boot 自动化配置

4.2.1 Spring Boot 应用启动
// 主应用类
@SpringBootApplication
@EnableAsync
@EnableScheduling
@EnableCaching
@EnableTransactionManagement
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
// 自定义启动配置
app.setBannerMode(Banner.Mode.CONSOLE);
app.setLogStartupInfo(true);
ConfigurableApplicationContext context = app.run(args);
// 应用启动后执行
checkBeans(context);
}
private static void checkBeans(ConfigurableApplicationContext context) {
logger.info("检查Spring Bean配置...");
String[] beanNames = context.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
if (beanName.contains("service") || beanName.contains("controller")) {
logger.debug("加载的Bean: {}", beanName);
}
}
}
}
// 配置类
@Configuration
@EnableConfigurationProperties({AppProperties.class, SecurityProperties.class})
public class AppConfig {
@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
@Bean
@ConditionalOnProperty(name = "app.cache.enabled", havingValue = "true")
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("users", "orders");
}
}
// 配置属性类
@ConfigurationProperties(prefix = "app")
@Component
@Validated
public class AppProperties {
@NotBlank
private String name;
@Min(1024)
@Max(65535)
private int port = 8080;
private Security security = new Security();
// getters and setters
public static class Security {
private boolean enabled = true;
private String secretKey;
// getters and setters
}
}
4.2.2 应用配置文件
# application.yml
spring:
application:
name: my-spring-app
profiles:
active: @activatedProperties@
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:password}
hikari:
maximum-pool-size: 20
minimum-idle: 5
jpa:
hibernate:
ddl-auto: validate
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
redis:
host: localhost
port: 6379
timeout: 2000ms
server:
port: 8080
servlet:
context-path: /api
compression:
enabled: true
app:
name: "My Application"
port: 8080
security:
enabled: true
secret-key: ${APP_SECRET:default-secret-key}
cache:
enabled: true
logging:
level:
com.example: DEBUG
org.springframework.security: INFO
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n"
file:
name: logs/application.log
max-size: 10MB

4.3 Spring MVC Web 开发

4.3.1 RESTful API 开发
// 统一响应格式
public class ApiResponse<T> {
  private boolean success;
  private String message;
  private T data;
  private String timestamp;
  public ApiResponse(boolean success, String message, T data) {
  this.success = success;
  this.message = message;
  this.data = data;
  this.timestamp = Instant.now().toString();
  }
  public static <T> ApiResponse<T> success(T data) {
    return new ApiResponse<>(true, "成功", data);
      }
      public static <T> ApiResponse<T> success(String message, T data) {
        return new ApiResponse<>(true, message, data);
          }
          public static <T> ApiResponse<T> error(String message) {
            return new ApiResponse<>(false, message, null);
              }
              // getters and setters
              }
              // 统一异常处理
              @ControllerAdvice
              @RestController
              public class GlobalExceptionHandler {
              private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
              @ExceptionHandler(EntityNotFoundException.class)
              @ResponseStatus(HttpStatus.NOT_FOUND)
              public ApiResponse<Void> handleEntityNotFound(EntityNotFoundException ex) {
                logger.warn("实体未找到: {}", ex.getMessage());
                return ApiResponse.error(ex.getMessage());
                }
                @ExceptionHandler(ValidationException.class)
                @ResponseStatus(HttpStatus.BAD_REQUEST)
                public ApiResponse<Void> handleValidationException(ValidationException ex) {
                  logger.warn("验证失败: {}", ex.getMessage());
                  return ApiResponse.error(ex.getMessage());
                  }
                  @ExceptionHandler(AccessDeniedException.class)
                  @ResponseStatus(HttpStatus.FORBIDDEN)
                  public ApiResponse<Void> handleAccessDenied(AccessDeniedException ex) {
                    logger.warn("访问被拒绝: {}", ex.getMessage());
                    return ApiResponse.error("没有访问权限");
                    }
                    @ExceptionHandler(Exception.class)
                    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
                    public ApiResponse<Void> handleGenericException(Exception ex) {
                      logger.error("服务器内部错误", ex);
                      return ApiResponse.error("服务器内部错误,请稍后重试");
                      }
                      // 处理方法参数验证错误
                      @ExceptionHandler(MethodArgumentNotValidException.class)
                      @ResponseStatus(HttpStatus.BAD_REQUEST)
                      public ApiResponse<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) {
                        Map<String, String> errors = new HashMap<>();
                          ex.getBindingResult().getFieldErrors()
                          .forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));
                          return new ApiResponse<>(false, "参数验证失败", errors);
                            }
                            }
                            // REST 控制器
                            @RestController
                            @RequestMapping("/api/v1/users")
                            @Validated
                            @Slf4j
                            public class UserController {
                            private final UserService userService;
                            public UserController(UserService userService) {
                            this.userService = userService;
                            }
                            @GetMapping
                            @PreAuthorize("hasRole('ADMIN')")
                            public ApiResponse<Page<UserDto>> getUsers(
                              @RequestParam(defaultValue = "0") int page,
                              @RequestParam(defaultValue = "20") int size,
                              @RequestParam(required = false) String search) {
                              Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
                              Page<UserDto> users = userService.getUsers(pageable, search);
                                return ApiResponse.success(users);
                                }
                                @GetMapping("/{id}")
                                public ApiResponse<UserDto> getUser(@PathVariable Long id) {
                                  UserDto user = userService.getUserById(id);
                                  return ApiResponse.success(user);
                                  }
                                  @PostMapping
                                  @ResponseStatus(HttpStatus.CREATED)
                                  public ApiResponse<UserDto> createUser(@Valid @RequestBody CreateUserRequest request) {
                                    UserDto createdUser = userService.createUser(request);
                                    return ApiResponse.success("用户创建成功", createdUser);
                                    }
                                    @PutMapping("/{id}")
                                    public ApiResponse<UserDto> updateUser(
                                      @PathVariable Long id,
                                      @Valid @RequestBody UpdateUserRequest request) {
                                      UserDto updatedUser = userService.updateUser(id, request);
                                      return ApiResponse.success("用户更新成功", updatedUser);
                                      }
                                      @DeleteMapping("/{id}")
                                      @ResponseStatus(HttpStatus.NO_CONTENT)
                                      public void deleteUser(@PathVariable Long id) {
                                      userService.deleteUser(id);
                                      }
                                      @GetMapping("/{id}/orders")
                                      public ApiResponse<List<OrderDto>> getUserOrders(@PathVariable Long id) {
                                        List<OrderDto> orders = userService.getUserOrders(id);
                                          return ApiResponse.success(orders);
                                          }
                                          }
                                          // DTO 类
                                          public class CreateUserRequest {
                                          @NotBlank(message = "邮箱不能为空")
                                          @Email(message = "邮箱格式不正确")
                                          private String email;
                                          @NotBlank(message = "姓名不能为空")
                                          @Size(min = 2, max = 50, message = "姓名长度必须在2-50个字符之间")
                                          private String name;
                                          @NotBlank(message = "密码不能为空")
                                          @Size(min = 6, message = "密码长度至少6位")
                                          @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).*$",
                                          message = "密码必须包含大小写字母和数字")
                                          private String password;
                                          // getters and setters
                                          }
                                          // 服务层实现
                                          @Service
                                          @Transactional(readOnly = true)
                                          @Slf4j
                                          public class UserService {
                                          private final UserRepository userRepository;
                                          private final UserMapper userMapper;
                                          private final PasswordEncoder passwordEncoder;
                                          public UserService(UserRepository userRepository, UserMapper userMapper,
                                          PasswordEncoder passwordEncoder) {
                                          this.userRepository = userRepository;
                                          this.userMapper = userMapper;
                                          this.passwordEncoder = passwordEncoder;
                                          }
                                          public Page<UserDto> getUsers(Pageable pageable, String search) {
                                            Specification<User> spec = buildSearchSpecification(search);
                                              Page<User> users = userRepository.findAll(spec, pageable);
                                                return users.map(userMapper::toDto);
                                                }
                                                public UserDto getUserById(Long id) {
                                                User user = userRepository.findById(id)
                                                .orElseThrow(() -> new EntityNotFoundException("用户不存在: " + id));
                                                return userMapper.toDto(user);
                                                }
                                                @Transactional
                                                public UserDto createUser(CreateUserRequest request) {
                                                // 检查邮箱是否已存在
                                                if (userRepository.existsByEmail(request.getEmail())) {
                                                throw new ValidationException("邮箱已存在: " + request.getEmail());
                                                }
                                                User user = new User();
                                                user.setEmail(request.getEmail());
                                                user.setName(request.getName());
                                                user.setPassword(passwordEncoder.encode(request.getPassword()));
                                                user.setStatus(UserStatus.ACTIVE);
                                                user.setCreatedAt(LocalDateTime.now());
                                                User savedUser = userRepository.save(user);
                                                log.info("创建用户成功: {}", savedUser.getEmail());
                                                return userMapper.toDto(savedUser);
                                                }
                                                @Transactional
                                                public UserDto updateUser(Long id, UpdateUserRequest request) {
                                                User user = userRepository.findById(id)
                                                .orElseThrow(() -> new EntityNotFoundException("用户不存在: " + id));
                                                user.setName(request.getName());
                                                user.setUpdatedAt(LocalDateTime.now());
                                                User updatedUser = userRepository.save(user);
                                                return userMapper.toDto(updatedUser);
                                                }
                                                @Transactional
                                                public void deleteUser(Long id) {
                                                User user = userRepository.findById(id)
                                                .orElseThrow(() -> new EntityNotFoundException("用户不存在: " + id));
                                                user.setStatus(UserStatus.DELETED);
                                                userRepository.save(user);
                                                log.info("删除用户: {}", id);
                                                }
                                                private Specification<User> buildSearchSpecification(String search) {
                                                  return (root, query, criteriaBuilder) -> {
                                                  if (StringUtils.isEmpty(search)) {
                                                  return criteriaBuilder.conjunction();
                                                  }
                                                  String likePattern = "%" + search.toLowerCase() + "%";
                                                  return criteriaBuilder.or(
                                                  criteriaBuilder.like(criteriaBuilder.lower(root.get("name")), likePattern),
                                                  criteriaBuilder.like(criteriaBuilder.lower(root.get("email")), likePattern)
                                                  );
                                                  };
                                                  }
                                                  }

第五部分:数据库与持久层技术

5.1 JPA 与 Hibernate

5.1.1 实体类映射
// 基类实体
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@CreatedDate
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@Version
private Long version;
// getters and setters
}
// 用户实体
@Entity
@Table(name = "users",
indexes = {
@Index(name = "idx_user_email", columnList = "email", unique = true),
@Index(name = "idx_user_status", columnList = "status")
})
@NamedQueries({
@NamedQuery(
name = "User.findByStatus",
query = "SELECT u FROM User u WHERE u.status = :status"
)
})
public class User extends BaseEntity {
@Column(name = "email", nullable = false, length = 100)
private String email;
@Column(name = "name", nullable = false, length = 50)
private String name;
@Column(name = "password_hash", nullable = false, length = 100)
private String password;
@Enumerated(EnumType.STRING)
@Column(name = "status", length = 20)
private UserStatus status = UserStatus.ACTIVE;
@Column(name = "last_login_at")
private LocalDateTime lastLoginAt;
// 一对一关系
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private UserProfile profile;
// 一对多关系
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OrderBy("createdAt DESC")
private List<Order> orders = new ArrayList<>();
  // 多对多关系
  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(
  name = "user_roles",
  joinColumns = @JoinColumn(name = "user_id"),
  inverseJoinColumns = @JoinColumn(name = "role_id")
  )
  private Set<Role> roles = new HashSet<>();
    // 构造函数
    public User() {}
    public User(String email, String name) {
    this.email = email;
    this.name = name;
    }
    // 业务方法
    public void addOrder(Order order) {
    orders.add(order);
    order.setUser(this);
    }
    public void removeOrder(Order order) {
    orders.remove(order);
    order.setUser(null);
    }
    public void addRole(Role role) {
    roles.add(role);
    role.getUsers().add(this);
    }
    // getters and setters
    }
    // 枚举定义
    public enum UserStatus {
    ACTIVE, INACTIVE, SUSPENDED, DELETED
    }
    // 订单实体
    @Entity
    @Table(name = "orders")
    public class Order extends BaseEntity {
    @Column(name = "order_number", unique = true, length = 20)
    private String orderNumber;
    @Column(name = "total_amount", precision = 10, scale = 2)
    private BigDecimal totalAmount;
    @Enumerated(EnumType.STRING)
    @Column(name = "status", length = 20)
    private OrderStatus status = OrderStatus.PENDING;
    // 多对一关系
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
    // 一对多关系
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrderItem> items = new ArrayList<>();
      // 嵌入式对象
      @Embedded
      private Address shippingAddress;
      // 业务方法
      public void addItem(OrderItem item) {
      items.add(item);
      item.setOrder(this);
      }
      public BigDecimal calculateTotal() {
      return items.stream()
      .map(OrderItem::getSubtotal)
      .reduce(BigDecimal.ZERO, BigDecimal::add);
      }
      // getters and setters
      }
      // 嵌入式地址类
      @Embeddable
      public class Address {
      @Column(name = "street", length = 100)
      private String street;
      @Column(name = "city", length = 50)
      private String city;
      @Column(name = "state", length = 50)
      private String state;
      @Column(name = "zip_code", length = 20)
      private String zipCode;
      @Column(name = "country", length = 50)
      private String country = "China";
      // getters and setters
      }
5.1.2 Repository 数据访问层
// 基础 Repository 接口
@NoRepositoryBean
public interface BaseRepository<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
  default Optional<T> findByIdOptional(ID id) {
    return findById(id);
    }
    List<T> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
      @Query("SELECT COUNT(e) FROM #{#entityName} e")
      long countAll();
      @Modifying
      @Query("UPDATE #{#entityName} e SET e.status = :status WHERE e.id = :id")
      int updateStatus(@Param("id") ID id, @Param("status") String status);
      }
      // 用户 Repository
      @Repository
      public interface UserRepository extends BaseRepository<User, Long> {
        // 派生查询方法
        Optional<User> findByEmail(String email);
          boolean existsByEmail(String email);
          List<User> findByStatusOrderByCreatedAtDesc(UserStatus status);
            List<User> findByNameContainingIgnoreCase(String name);
              // @Query 注解查询
              @Query("SELECT u FROM User u WHERE u.email LIKE %:domain")
              List<User> findByEmailDomain(@Param("domain") String domain);
                @Query("SELECT u.name, COUNT(o) FROM User u LEFT JOIN u.orders o GROUP BY u.id")
                List<Object[]> findUserOrderCount();
                  // 原生 SQL 查询
                  @Query(value = "SELECT * FROM users WHERE DATE(created_at) = :date", nativeQuery = true)
                  List<User> findByCreatedDate(@Param("date") LocalDate date);
                    // 分页查询
                    Page<User> findByStatus(UserStatus status, Pageable pageable);
                      // 使用 Specification 进行复杂查询
                      default Page<User> findActiveUsersWithOrders(Pageable pageable) {
                        return findAll((root, query, criteriaBuilder) -> {
                        List<Predicate> predicates = new ArrayList<>();
                          predicates.add(criteriaBuilder.equal(root.get("status"), UserStatus.ACTIVE));
                          predicates.add(criteriaBuilder.isNotEmpty(root.get("orders")));
                          return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
                          }, pageable);
                          }
                          }
                          // 自定义 Repository 实现
                          public interface UserRepositoryCustom {
                          List<User> findComplexUsers(UserSearchCriteria criteria);
                            Page<User> searchUsers(UserSearchCriteria criteria, Pageable pageable);
                              }
                              // 自定义 Repository 实现类
                              @Repository
                              @Transactional(readOnly = true)
                              public class UserRepositoryImpl implements UserRepositoryCustom {
                              @PersistenceContext
                              private EntityManager entityManager;
                              @Override
                              public List<User> findComplexUsers(UserSearchCriteria criteria) {
                                CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                                CriteriaQuery<User> query = cb.createQuery(User.class);
                                  Root<User> root = query.from(User.class);
                                    List<Predicate> predicates = buildPredicates(criteria, cb, root);
                                      query.where(predicates.toArray(new Predicate[0]));
                                      TypedQuery<User> typedQuery = entityManager.createQuery(query);
                                        return typedQuery.getResultList();
                                        }
                                        @Override
                                        public Page<User> searchUsers(UserSearchCriteria criteria, Pageable pageable) {
                                          CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                                          CriteriaQuery<User> query = cb.createQuery(User.class);
                                            Root<User> root = query.from(User.class);
                                              List<Predicate> predicates = buildPredicates(criteria, cb, root);
                                                query.where(predicates.toArray(new Predicate[0]));
                                                // 排序
                                                List<Order> orders = new ArrayList<>();
                                                  for (Sort.Order sortOrder : pageable.getSort()) {
                                                  if (sortOrder.isAscending()) {
                                                  orders.add(cb.asc(root.get(sortOrder.getProperty())));
                                                  } else {
                                                  orders.add(cb.desc(root.get(sortOrder.getProperty())));
                                                  }
                                                  }
                                                  query.orderBy(orders);
                                                  TypedQuery<User> typedQuery = entityManager.createQuery(query);
                                                    typedQuery.setFirstResult((int) pageable.getOffset());
                                                    typedQuery.setMaxResults(pageable.getPageSize());
                                                    List<User> result = typedQuery.getResultList();
                                                      // 获取总数
                                                      Long total = getTotalCount(criteria);
                                                      return new PageImpl<>(result, pageable, total);
                                                        }
                                                        private List<Predicate> buildPredicates(UserSearchCriteria criteria,
                                                          CriteriaBuilder cb, Root<User> root) {
                                                            List<Predicate> predicates = new ArrayList<>();
                                                              if (StringUtils.hasText(criteria.getKeyword())) {
                                                              String likePattern = "%" + criteria.getKeyword().toLowerCase() + "%";
                                                              predicates.add(cb.or(
                                                              cb.like(cb.lower(root.get("name")), likePattern),
                                                              cb.like(cb.lower(root.get("email")), likePattern)
                                                              ));
                                                              }
                                                              if (criteria.getStatus() != null) {
                                                              predicates.add(cb.equal(root.get("status"), criteria.getStatus()));
                                                              }
                                                              if (criteria.getStartDate() != null) {
                                                              predicates.add(cb.greaterThanOrEqualTo(root.get("createdAt"),
                                                              criteria.getStartDate()));
                                                              }
                                                              if (criteria.getEndDate() != null) {
                                                              predicates.add(cb.lessThanOrEqualTo(root.get("createdAt"),
                                                              criteria.getEndDate()));
                                                              }
                                                              return predicates;
                                                              }
                                                              private Long getTotalCount(UserSearchCriteria criteria) {
                                                              CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                                                              CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
                                                                Root<User> root = countQuery.from(User.class);
                                                                  List<Predicate> predicates = buildPredicates(criteria, cb, root);
                                                                    countQuery.select(cb.count(root)).where(predicates.toArray(new Predicate[0]));
                                                                    return entityManager.createQuery(countQuery).getSingleResult();
                                                                    }
                                                                    }
                                                                    // 搜索条件类
                                                                    @Data
                                                                    public class UserSearchCriteria {
                                                                    private String keyword;
                                                                    private UserStatus status;
                                                                    private LocalDateTime startDate;
                                                                    private LocalDateTime endDate;
                                                                    private Boolean hasOrders;
                                                                    }

5.2 数据库迁移与版本控制

5.2.1 Flyway 数据库迁移
-- V1__Create_users_table.sql
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(100) NOT NULL UNIQUE,
name VARCHAR(50) NOT NULL,
password_hash VARCHAR(100) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
version BIGINT DEFAULT 0
);
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_user_status ON users(status);
-- V2__Create_orders_table.sql
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_number VARCHAR(20) UNIQUE NOT NULL,
user_id BIGINT NOT NULL,
total_amount DECIMAL(10,2),
status VARCHAR(20) DEFAULT 'PENDING',
shipping_street VARCHAR(100),
shipping_city VARCHAR(50),
shipping_state VARCHAR(50),
shipping_zip_code VARCHAR(20),
shipping_country VARCHAR(50) DEFAULT 'China',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
version BIGINT DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_order_user_id ON orders(user_id);
CREATE INDEX idx_order_number ON orders(order_number);
-- V3__Create_order_items_table.sql
CREATE TABLE order_items (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_id BIGINT NOT NULL,
product_name VARCHAR(100) NOT NULL,
quantity INT NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
subtotal DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
);
-- V4__Add_last_login_to_users.sql
ALTER TABLE users ADD COLUMN last_login_at TIMESTAMP NULL;
-- V5__Create_user_roles.sql
CREATE TABLE roles (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
description VARCHAR(200),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE user_roles (
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
assigned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
);
-- V6__Insert_initial_data.sql
INSERT INTO roles (name, description) VALUES
('ADMIN', '系统管理员'),
('USER', '普通用户'),
('MANAGER', '经理');
-- 回滚脚本 R__Drop_user_roles.sql
DROP TABLE IF EXISTS user_roles;
DROP TABLE IF EXISTS roles;
5.2.2 Flyway 配置
@Configuration
public class FlywayConfig {
@Bean
public FlywayMigrationStrategy flywayMigrationStrategy() {
return flyway -> {
// 在迁移前执行的操作
log.info("开始数据库迁移...");
flyway.migrate();
};
}
@Bean
@ConfigurationProperties(prefix = "spring.flyway")
public FlywayProperties flywayProperties() {
return new FlywayProperties();
}
}
# application.yml 中的 Flyway 配置
spring:
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
baseline-version: 1
validate-on-migrate: true
out-of-order: false
clean-disabled: true
table: flyway_schema_history
placeholders:
table-prefix: ""

第六部分:高级主题与最佳实践

6.1 性能优化与缓存

6.1.1 Redis 缓存集成
// 缓存配置
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.disableCachingNullValues()
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.withInitialCacheConfigurations(getCacheConfigurations())
.transactionAware()
.build();
}
private Map<String, RedisCacheConfiguration> getCacheConfigurations() {
  Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>();
    cacheConfigs.put("users", RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofHours(1))
    .serializeValuesWith(RedisSerializationContext.SerializationPair
    .fromSerializer(new GenericJackson2JsonRedisSerializer())));
    cacheConfigs.put("products", RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofMinutes(15)));
    return cacheConfigs;
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
      RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        // 使用 Jackson 序列化
        Jackson2JsonRedisSerializer<Object> serializer =
          new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper mapper = new ObjectMapper();
            mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(),
            ObjectMapper.DefaultTyping.NON_FINAL);
            serializer.setObjectMapper(mapper);
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(serializer);
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setHashValueSerializer(serializer);
            template.afterPropertiesSet();
            return template;
            }
            }
            // 缓存服务
            @Service
            @Slf4j
            public class CacheService {
            private final RedisTemplate<String, Object> redisTemplate;
              private final ObjectMapper objectMapper;
              public CacheService(RedisTemplate<String, Object> redisTemplate,
                ObjectMapper objectMapper) {
                this.redisTemplate = redisTemplate;
                this.objectMapper = objectMapper;
                }
                public <T> void set(String key, T value, Duration ttl) {
                  try {
                  redisTemplate.opsForValue().set(key, value, ttl);
                  } catch (Exception e) {
                  log.error("Redis 设置缓存失败 key: {}", key, e);
                  }
                  }
                  @SuppressWarnings("unchecked")
                  public <T> T get(String key, Class<T> type) {
                    try {
                    Object value = redisTemplate.opsForValue().get(key);
                    if (value == null) {
                    return null;
                    }
                    if (type.isInstance(value)) {
                    return (T) value;
                    }
                    // 类型转换
                    return objectMapper.convertValue(value, type);
                    } catch (Exception e) {
                    log.error("Redis 获取缓存失败 key: {}", key, e);
                    return null;
                    }
                    }
                    public boolean delete(String key) {
                    try {
                    return Boolean.TRUE.equals(redisTemplate.delete(key));
                    } catch (Exception e) {
                    log.error("Redis 删除缓存失败 key: {}", key, e);
                    return false;
                    }
                    }
                    public boolean exists(String key) {
                    try {
                    return Boolean.TRUE.equals(redisTemplate.hasKey(key));
                    } catch (Exception e) {
                    log.error("Redis 检查键存在失败 key: {}", key, e);
                    return false;
                    }
                    }
                    public void setHash(String key, String hashKey, Object value) {
                    try {
                    redisTemplate.opsForHash().put(key, hashKey, value);
                    } catch (Exception e) {
                    log.error("Redis 设置哈希缓存失败 key: {}, hashKey: {}", key, hashKey, e);
                    }
                    }
                    @SuppressWarnings("unchecked")
                    public <T> T getHash(String key, String hashKey, Class<T> type) {
                      try {
                      Object value = redisTemplate.opsForHash().get(key, hashKey);
                      if (value == null) {
                      return null;
                      }
                      if (type.isInstance(value)) {
                      return (T) value;
                      }
                      return objectMapper.convertValue(value, type);
                      } catch (Exception e) {
                      log.error("Redis 获取哈希缓存失败 key: {}, hashKey: {}", key, hashKey, e);
                      return null;
                      }
                      }
                      }
                      // 使用缓存的服务
                      @Service
                      @Slf4j
                      public class CachedUserService {
                      private final UserRepository userRepository;
                      private final CacheService cacheService;
                      private final UserMapper userMapper;
                      private static final String USER_CACHE_PREFIX = "user:";
                      private static final String USER_LIST_CACHE_KEY = "users:list";
                      private static final Duration USER_CACHE_TTL = Duration.ofHours(1);
                      public CachedUserService(UserRepository userRepository, CacheService cacheService,
                      UserMapper userMapper) {
                      this.userRepository = userRepository;
                      this.cacheService = cacheService;
                      this.userMapper = userMapper;
                      }
                      @Cacheable(value = "users", key = "#id", unless = "#result == null")
                      public UserDto getUserById(Long id) {
                      log.debug("从数据库获取用户: {}", id);
                      User user = userRepository.findById(id)
                      .orElseThrow(() -> new EntityNotFoundException("用户不存在: " + id));
                      return userMapper.toDto(user);
                      }
                      @Cacheable(value = "users", key = "#email", unless = "#result == null")
                      public UserDto getUserByEmail(String email) {
                      log.debug("从数据库获取用户: {}", email);
                      User user = userRepository.findByEmail(email)
                      .orElseThrow(() -> new EntityNotFoundException("用户不存在: " + email));
                      return userMapper.toDto(user);
                      }
                      @Caching(
                      put = {
                      @CachePut(value = "users", key = "#result.id"),
                      @CachePut(value = "users", key = "#result.email")
                      },
                      evict = {
                      @CacheEvict(value = "users", key = "'list'"),
                      @CacheEvict(value = "users", key = "'search:' + #result.status")
                      }
                      )
                      public UserDto updateUser(UserDto userDto) {
                      User user = userRepository.findById(userDto.getId())
                      .orElseThrow(() -> new EntityNotFoundException("用户不存在: " + userDto.getId()));
                      userMapper.updateUserFromDto(userDto, user);
                      User updatedUser = userRepository.save(user);
                      log.info("更新用户: {}", userDto.getId());
                      return userMapper.toDto(updatedUser);
                      }
                      @CacheEvict(value = "users", allEntries = true)
                      public void evictAllUserCaches() {
                      log.info("清除所有用户缓存");
                      }
                      // 手动缓存管理
                      public List<UserDto> getActiveUsers() {
                        String cacheKey = "users:active";
                        // 尝试从缓存获取
                        List<UserDto> cachedUsers = cacheService.get(cacheKey, List.class);
                          if (cachedUsers != null) {
                          log.debug("从缓存获取活跃用户列表");
                          return cachedUsers;
                          }
                          // 从数据库获取
                          log.debug("从数据库获取活跃用户列表");
                          List<User> users = userRepository.findByStatusOrderByCreatedAtDesc(UserStatus.ACTIVE);
                            List<UserDto> userDtos = users.stream()
                              .map(userMapper::toDto)
                              .collect(Collectors.toList());
                              // 设置缓存
                              cacheService.set(cacheKey, userDtos, Duration.ofMinutes(30));
                              return userDtos;
                              }
                              }

6.2 安全与认证授权

6.2.1 Spring Security 配置
// 安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig {
private final UserDetailsService userDetailsService;
private final JwtTokenProvider jwtTokenProvider;
public SecurityConfig(UserDetailsService userDetailsService,
JwtTokenProvider jwtTokenProvider) {
this.userDetailsService = userDetailsService;
this.jwtTokenProvider = jwtTokenProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.apply(new JwtConfigurer(jwtTokenProvider));
return http.build();
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
// JWT 配置
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
  private final JwtTokenProvider jwtTokenProvider;
  public JwtConfigurer(JwtTokenProvider jwtTokenProvider) {
  this.jwtTokenProvider = jwtTokenProvider;
  }
  @Override
  public void configure(HttpSecurity http) {
  JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider);
  http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
  }
  }
  // JWT Token 过滤器
  public class JwtTokenFilter extends OncePerRequestFilter {
  private final JwtTokenProvider jwtTokenProvider;
  public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
  this.jwtTokenProvider = jwtTokenProvider;
  }
  @Override
  protected void doFilterInternal(HttpServletRequest request,
  HttpServletResponse response,
  FilterChain filterChain) throws ServletException, IOException {
  String token = resolveToken(request);
  if (token != null && jwtTokenProvider.validateToken(token)) {
  Authentication auth = jwtTokenProvider.getAuthentication(token);
  SecurityContextHolder.getContext().setAuthentication(auth);
  }
  filterChain.doFilter(request, response);
  }
  private String resolveToken(HttpServletRequest request) {
  String bearerToken = request.getHeader("Authorization");
  if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
  return bearerToken.substring(7);
  }
  return null;
  }
  }
  // JWT Token 提供者
  @Component
  public class JwtTokenProvider {
  @Value("${app.jwt.secret:defaultSecret}")
  private String jwtSecret;
  @Value("${app.jwt.expiration:86400000}")
  private long jwtExpirationMs;
  private static final Logger logger = LoggerFactory.getLogger(JwtTokenProvider.class);
  public String generateToken(Authentication authentication) {
  UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
  Date now = new Date();
  Date expiryDate = new Date(now.getTime() + jwtExpirationMs);
  return Jwts.builder()
  .setSubject(userPrincipal.getUsername())
  .setIssuedAt(now)
  .setExpiration(expiryDate)
  .signWith(SignatureAlgorithm.HS512, jwtSecret)
  .compact();
  }
  public String getUsernameFromToken(String token) {
  Claims claims = Jwts.parser()
  .setSigningKey(jwtSecret)
  .parseClaimsJws(token)
  .getBody();
  return claims.getSubject();
  }
  public boolean validateToken(String token) {
  try {
  Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
  return true;
  } catch (SignatureException ex) {
  logger.error("Invalid JWT signature");
  } catch (MalformedJwtException ex) {
  logger.error("Invalid JWT token");
  } catch (ExpiredJwtException ex) {
  logger.error("Expired JWT token");
  } catch (UnsupportedJwtException ex) {
  logger.error("Unsupported JWT token");
  } catch (IllegalArgumentException ex) {
  logger.error("JWT claims string is empty");
  }
  return false;
  }
  public Authentication getAuthentication(String token) {
  String username = getUsernameFromToken(token);
  UserDetails userDetails = loadUserByUsername(username);
  return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
  }
  private UserDetails loadUserByUsername(String username) {
  // 实现用户加载逻辑
  return null; // 实际应该从数据库加载
  }
  }
  // 用户详情服务
  @Service
  @Transactional(readOnly = true)
  public class CustomUserDetailsService implements UserDetailsService {
  private final UserRepository userRepository;
  public CustomUserDetailsService(UserRepository userRepository) {
  this.userRepository = userRepository;
  }
  @Override
  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
  User user = userRepository.findByEmail(email)
  .orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + email));
  return UserPrincipal.create(user);
  }
  public UserDetails loadUserById(Long id) {
  User user = userRepository.findById(id)
  .orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + id));
  return UserPrincipal.create(user);
  }
  }
  // 用户主体类
  public class UserPrincipal implements UserDetails {
  private Long id;
  private String email;
  private String password;
  private Collection<? extends GrantedAuthority> authorities;
    public UserPrincipal(Long id, String email, String password,
    Collection<? extends GrantedAuthority> authorities) {
      this.id = id;
      this.email = email;
      this.password = password;
      this.authorities = authorities;
      }
      public static UserPrincipal create(User user) {
      List<GrantedAuthority> authorities = user.getRoles().stream()
        .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
        .collect(Collectors.toList());
        return new UserPrincipal(
        user.getId(),
        user.getEmail(),
        user.getPassword(),
        authorities
        );
        }
        // UserDetails 接口方法实现
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
          return authorities;
          }
          @Override
          public String getPassword() {
          return password;
          }
          @Override
          public String getUsername() {
          return email;
          }
          @Override
          public boolean isAccountNonExpired() {
          return true;
          }
          @Override
          public boolean isAccountNonLocked() {
          return true;
          }
          @Override
          public boolean isCredentialsNonExpired() {
          return true;
          }
          @Override
          public boolean isEnabled() {
          return true;
          }
          // getters
          public Long getId() {
          return id;
          }
          }

6.3 微服务与分布式系统

6.3.1 Spring Cloud 微服务配置
// 服务注册与发现
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
// 配置类
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
}
// Feign 客户端
@FeignClient(name = "order-service", path = "/api/orders")
public interface OrderServiceClient {
@GetMapping("/user/{userId}")
List<OrderDto> getUserOrders(@PathVariable("userId") Long userId);
  @PostMapping
  OrderDto createOrder(@RequestBody CreateOrderRequest request);
  @PutMapping("/{orderId}/status")
  OrderDto updateOrderStatus(@PathVariable("orderId") Long orderId,
  @RequestBody UpdateOrderStatusRequest request);
  }
  // 服务调用示例
  @Service
  @Slf4j
  public class UserOrderService {
  private final OrderServiceClient orderServiceClient;
  private final CircuitBreakerFactory circuitBreakerFactory;
  public UserOrderService(OrderServiceClient orderServiceClient,
  CircuitBreakerFactory circuitBreakerFactory) {
  this.orderServiceClient = orderServiceClient;
  this.circuitBreakerFactory = circuitBreakerFactory;
  }
  public List<OrderDto> getUserOrdersWithFallback(Long userId) {
    CircuitBreaker circuitBreaker = circuitBreakerFactory.create("order-service");
    return circuitBreaker.run(
    () -> orderServiceClient.getUserOrders(userId),
    throwable -> {
    log.warn("订单服务调用失败,使用降级策略", throwable);
    return Collections.emptyList();
    }
    );
    }
    @Retry(name = "order-service", fallbackMethod = "createOrderFallback")
    public OrderDto createOrderWithRetry(CreateOrderRequest request) {
    return orderServiceClient.createOrder(request);
    }
    public OrderDto createOrderFallback(CreateOrderRequest request, Exception ex) {
    log.error("创建订单重试失败", ex);
    // 返回默认值或抛出业务异常
    throw new BusinessException("订单服务暂时不可用");
    }
    }
    // 配置中心配置
    @Configuration
    @RefreshScope
    public class AppConfig {
    @Value("${app.feature.enabled:false}")
    private boolean featureEnabled;
    @Value("${app.cache.ttl:300}")
    private long cacheTtl;
    @Bean
    @RefreshScope
    public CacheManager cacheManager() {
    // 动态配置的缓存管理器
    return new ConcurrentMapCacheManager();
    }
    // getters
    }

第七部分:部署与运维

7.1 Docker 容器化部署

7.1.1 Dockerfile 配置
# 多阶段构建 Dockerfile
FROM openjdk:11-jdk-slim as builder
# 安装 Maven
RUN apt-get update && apt-get install -y maven
WORKDIR /app
COPY pom.xml .
COPY src ./src
# 构建应用
RUN mvn clean package -DskipTests
# 运行时镜像
FROM openjdk:11-jre-slim
# 安装必要的工具
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/*
# 创建应用用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 创建应用目录
RUN mkdir -p /app/logs && chown -R appuser:appuser /app
USER appuser
WORKDIR /app
# 复制构建结果
COPY --from=builder /app/target/*.jar app.jar
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8080/actuator/health || exit 1
# 环境变量
ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -Djava.security.egd=file:/dev/./urandom"
ENV SPRING_PROFILES_ACTIVE="docker"
# 暴露端口
EXPOSE 8080
# 启动应用
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
7.1.2 Docker Compose 配置
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DB_HOST=mysql
- REDIS_HOST=redis
depends_on:
- mysql
- redis
networks:
- app-network
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512M
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: apppassword
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- app-network
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
redis:
image: redis:6.2-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
networks:
- app-network
command: redis-server --appendonly yes
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/ssl:/etc/nginx/ssl
depends_on:
- app
networks:
- app-network
volumes:
mysql-data:
redis-data:
networks:
app-network:
driver: bridge

7.2 监控与日志

7.2.1 Spring Boot Actuator 配置
# 监控配置
management:
endpoints:
web:
exposure:
include: health,info,metrics,loggers,prometheus
base-path: /actuator
endpoint:
health:
show-details: always
show-components: always
metrics:
enabled: true
loggers:
enabled: true
metrics:
export:
prometheus:
enabled: true
distribution:
percentiles-histogram:
http.server.requests: true
info:
env:
enabled: true
7.2.2 自定义健康检查
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
private final DataSource dataSource;
public DatabaseHealthIndicator(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Health health() {
try (Connection connection = dataSource.getConnection()) {
// 执行简单的数据库检查
try (Statement statement = connection.createStatement()) {
statement.execute("SELECT 1");
}
return Health.up()
.withDetail("database", "MySQL")
.withDetail("validationQuery", "SELECT 1")
.build();
} catch (Exception e) {
return Health.down(e)
.withDetail("database", "MySQL")
.withDetail("error", e.getMessage())
.build();
}
}
}
@Component
public class RedisHealthIndicator implements HealthIndicator {
private final RedisTemplate<String, Object> redisTemplate;
  public RedisHealthIndicator(RedisTemplate<String, Object> redisTemplate) {
    this.redisTemplate = redisTemplate;
    }
    @Override
    public Health health() {
    try {
    // 执行简单的 Redis 操作
    String testKey = "health:check";
    redisTemplate.opsForValue().set(testKey, "test", Duration.ofSeconds(10));
    String value = (String) redisTemplate.opsForValue().get(testKey);
    if ("test".equals(value)) {
    return Health.up()
    .withDetail("redis", "connected")
    .build();
    } else {
    return Health.down()
    .withDetail("redis", "unexpected response")
    .build();
    }
    } catch (Exception e) {
    return Health.down(e)
    .withDetail("redis", "connection failed")
    .withDetail("error", e.getMessage())
    .build();
    }
    }
    }

第八部分:学习路线与持续提升

8.1 分阶段学习计划

阶段一:基础入门(1-2个月)
  1. Java 语言基础
    • 语法、面向对象、集合框架
    • 异常处理、IO 操作、多线程
  2. 开发工具掌握
    • IntelliJ IDEA 使用
    • Maven/Gradle 构建工具
    • Git 版本控制
阶段二:Spring 框架(2-3个月)
  1. Spring Core
    • IOC、DI、AOP 概念
    • Bean 生命周期管理
  2. Spring Boot
    • 自动配置原理
    • Starter 使用
    • 应用配置管理
  3. 数据访问
    • JPA/Hibernate
    • 事务管理
    • 数据库迁移
阶段三:高级特性(2-3个月)
  1. 微服务架构
    • Spring Cloud 组件
    • 服务注册发现
    • 配置中心
  2. 性能优化
    • 缓存策略
    • 数据库优化
    • JVM 调优
  3. 安全防护
    • Spring Security
    • OAuth2/JWT
    • 安全最佳实践
阶段四:生产实践(持续)
  1. 容器化部署
    • Docker/Kubernetes
    • CI/CD 流水线
  2. 监控运维
    • 应用监控
    • 日志分析
    • 性能调优
  3. 架构设计
    • 系统架构模式
    • 领域驱动设计
    • 代码重构

8.2 持续学习资源

官方文档
在线课程
  • Spring 官方教程
  • Baeldung Java/Spring 教程
  • Java Brains YouTube 频道
实践项目
  • 个人博客系统
  • 电商平台
  • 微服务示例项目
  • 开源项目贡献

8.3 社区参与

技术社区
  • Stack Overflow
  • GitHub
  • 掘金、CSDN
  • 公司内部技术分享
持续提升建议
  1. 代码审查:参与团队代码审查,学习优秀代码风格
  2. 技术分享:定期进行技术分享,巩固知识
  3. 开源贡献:参与开源项目,了解最佳实践
  4. 技术博客:撰写技术博客,加深理解
  5. 参加技术会议:了解行业最新动态

总结

从 .NET 转型到 Java 是一个系统性的过程,需要从语言基础开始,逐步深入到框架使用、系统架构和运维部署。关键成功因素包括:

  1. 扎实的基础:深入理解 Java 语言特性和 JVM 原理
  2. 框架熟练度:掌握 Spring 生态系统的核心组件
  3. 工程化能力:熟悉构建工具、测试框架和 CI/CD
  4. 架构思维:理解微服务、分布式系统设计原则
  5. 持续学习:跟上技术发展趋势,不断更新知识体系

通过系统的学习和实践,.NET 开发者可以成功转型为 Java 开发者,并在新的技术栈中发挥更大的价值。记住,转型不仅是技术栈的切换,更是思维方式和开发理念的更新。保持开放的心态和持续学习的态度,是成功转型的关键。

posted @ 2025-10-15 08:44  wzzkaifa  阅读(4)  评论(0)    收藏  举报