本文详细介绍了Java全栈入门的相关知识,涵盖了Java基础、Web开发、前端技术以及实战项目与部署等内容。通过本文,读者可以全面了解并掌握Java全栈开发的基本技能。文章从安装Java开发环境开始,逐步讲解了Java语言基础、面向对象编程、Web开发实践以及前端技术基础。
Java全栈入门教程:一步步打造你的全栈开发技能 Java基础入门Java简介
Java是一种广泛使用的面向对象编程语言,由Sun Microsystems(已被Oracle收购)开发,最初是为了开发消费级电子产品的嵌入式系统。Java具有跨平台性,这意味着Java程序可以在任何支持Java的平台上运行,使用相同的代码。Java具有简单、面向对象、分布、健壮、安全、结构中立、可移植、性能良好、解释执行、可跨平台等特点。
安装Java开发环境
安装Java环境主要分为两步:安装JDK(Java Development Kit)和设置环境变量。
-
下载并安装JDK:
- 访问Oracle官方网站下载最新版本的JDK。
- 安装过程中,可以选择合适的安装目录。
- 设置环境变量:
- 在Windows系统中,右键点击"此电脑",选择“属性” -> “高级系统设置” -> “环境变量”。
- 在系统变量中新建两个变量:
JAVA_HOME
,值为JDK的安装路径。Path
,追加%JAVA_HOME%\bin
。
- 在Linux或macOS系统中,编辑
~/.bashrc
或~/.zshrc
文件,添加:export JAVA_HOME=/path/to/jdk export PATH=$JAVA_HOME/bin:$PATH
第一个Java程序
编写第一个Java程序,输出"Hello, World!"。
- 使用文本编辑器创建一个名为
HelloWorld.java
的文件。 - 编写代码:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
- 在命令行中编译和运行:
javac HelloWorld.java java HelloWorld
Java语言基础语法
注释
Java支持三种类型的注释:
- 单行注释:
//
- 多行注释:
/* ... */
- 文档注释:
/** ... */
// 单行注释
/* 多行注释 */
/**
* 文档注释
*/
文本与字符串
在Java中,文本采用字符串(String)类型表示。字符串是不可变的,即一旦创建后,其内容不能更改。
String str = "Hello";
String str2 = new String("World");
System.out.println(str + " " + str2);
数据类型与变量
Java的数据类型分为基本数据类型和引用数据类型。
基本数据类型
int num = 10;
float price = 19.99f;
double rate = 0.01;
char letter = 'A';
boolean flag = true;
引用数据类型
String name = "Alice";
String[] names = {"Alice", "Bob", "Charlie"};
List<String> list = Arrays.asList("Hello", "World");
变量声明
int x; // 声明变量,尚未赋值
int y = 5; // 声明并初始化变量
常量
使用final
关键字声明常量。
final int MAX = 100;
控制流程语句
if语句
int age = 18;
if (age >= 18) {
System.out.println("成年人");
} else {
System.out.println("未成年人");
}
switch语句
String day = "Monday";
switch (day) {
case "Monday":
System.out.println("星期一");
break;
case "Tuesday":
System.out.println("星期二");
break;
default:
System.out.println("其他日期");
}
循环语句
for循环
for (int i = 0; i < 10; i++) {
System.out.print(i + " ");
}
while循环
int i = 0;
while (i < 10) {
System.out.print(i + " ");
i++;
}
do-while循环
int i = 0;
do {
System.out.print(i + " ");
i++;
} while (i < 10);
数组与循环
数组
int[] numbers = new int[5];
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
numbers[4] = 5;
// 使用for循环打印数组
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
Java面向对象编程
类与对象的概念
Java是面向对象的语言,所有程序都是通过类和对象进行组织的。
类的定义
class Person {
String name;
int age;
void sayHello() {
System.out.println("Hello, I am " + name);
}
}
对象的创建
Person person = new Person();
person.name = "Alice";
person.age = 25;
person.sayHello();
构造函数与析构函数
构造函数
class Person {
String name;
int age;
// 构造函数
Person(String name, int age) {
this.name = name;
this.age = age;
}
void sayHello() {
System.out.println("Hello, I am " + name);
}
}
Person person = new Person("Alice", 25);
person.sayHello();
析构函数
Java中没有析构函数,垃圾回收器自动管理内存释放。
继承与多态
继承
class Animal {
void sound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog: Woof");
}
}
class Cat extends Animal {
void sound() {
System.out.println("Cat: Meow");
}
}
Animal animal = new Animal();
Animal dog = new Dog();
Animal cat = new Cat();
animal.sound();
dog.sound();
cat.sound();
多态
class Animal {
void sound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog: Woof");
}
}
class Cat extends Animal {
void sound() {
System.out.println("Cat: Meow");
}
}
public static void makeSound(Animal animal) {
animal.sound();
}
public static void main(String[] args) {
Animal animal = new Animal();
Animal dog = new Dog();
Animal cat = new Cat();
makeSound(animal);
makeSound(dog);
makeSound(cat);
}
接口与抽象类
接口
interface AnimalSound {
void sound();
}
class Dog implements AnimalSound {
public void sound() {
System.out.println("Dog: Woof");
}
}
class Cat implements AnimalSound {
public void sound() {
System.out.println("Cat: Meow");
}
}
public static void makeSound(AnimalSound animal) {
animal.sound();
}
public static void main(String[] args) {
AnimalSound dog = new Dog();
AnimalSound cat = new Cat();
makeSound(dog);
makeSound(cat);
}
抽象类
abstract class Animal {
public abstract void sound();
}
class Dog extends Animal {
public void sound() {
System.out.println("Dog: Woof");
}
}
class Cat extends Animal {
public void sound() {
System.out.println("Cat: Meow");
}
}
public static void makeSound(Animal animal) {
animal.sound();
}
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
makeSound(dog);
makeSound(cat);
}
包与访问控制
包
package com.example;
import com.example.Animal;
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.sound();
}
}
访问控制
public class Example {
public String publicField = "Public";
protected String protectedField = "Protected";
String defaultField = "Default";
private String privateField = "Private";
public void publicMethod() {
System.out.println("Public Method");
}
protected void protectedMethod() {
System.out.println("Protected Method");
}
void defaultMethod() {
System.out.println("Default Method");
}
private void privateMethod() {
System.out.println("Private Method");
}
}
Java Web开发入门
Web开发基础
Web开发涉及前端和后端技术,前端负责用户界面,后端负责数据处理和逻辑实现。
Web开发中常用的技术有HTML、CSS、JavaScript、服务器端技术(如Java、Python、PHP)和数据库技术(如MySQL、PostgreSQL)。
Servlet与JSP
Servlet
Servlet是运行在Java平台上的服务器端程序,用于接收和响应客户端请求。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorldServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Hello World</title></head>");
out.println("<body>");
out.println("<h1>Hello World</h1>");
out.println("</body>");
out.println("</html>");
}
}
JSP
JSP(JavaServer Pages)是一种动态网页技术标准,使用Java语言编写。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Java Web框架(如Spring Boot)
Spring Boot简介
Spring Boot简化了基于Spring的应用程序的开发,提供了自动配置功能,快速构建独立的、生产级别的基于Spring的应用程序。
创建Spring Boot项目
- 使用Spring Initializr创建项目。
- 添加必要的依赖(如Thymeleaf、Spring Web、Spring Data JPA等)。
- 编写控制器和视图。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
数据库连接与操作
JDBC连接数据库
import java.sql.*;
public class JdbcExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydatabase";
String user = "root";
String password = "password";
try (Connection con = DriverManager.getConnection(url, user, password);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
while (rs.next()) {
System.out.println(rs.getString("name") + " " + rs.getString("email"));
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
使用Spring Data JPA操作数据库
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
前端技术简介(HTML,CSS,JavaScript)
HTML
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Welcome to My Page</h1>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="script.js"></script>
</body>
</html>
CSS
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
h1 {
color: #333;
}
JavaScript
document.addEventListener("DOMContentLoaded", function() {
document.querySelector("h1").textContent = "My Dynamic Page";
});
数据库设计与SQL
SQL简介
SQL(Structured Query Language)是用于管理和操作关系数据库的标准语言。
常用SQL命令
-- 创建数据库
CREATE DATABASE mydatabase;
-- 创建表
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100)
);
-- 插入数据
INSERT INTO users VALUES (1, 'Alice', 'alice@example.com');
INSERT INTO users VALUES (2, 'Bob', 'bob@example.com');
-- 查询数据
SELECT * FROM users;
-- 更新数据
UPDATE users SET email = 'newemail@example.com' WHERE id = 1;
-- 删除数据
DELETE FROM users WHERE id = 2;
Java后端开发实践
RESTful API设计
RESTful API设计注重API的资源性、无状态性、分层系统和统一接口。
设计示例
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public List<User> getUsers() {
return userRepository.findAll();
}
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException(id));
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userRepository.save(user);
}
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
User existingUser = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException(id));
existingUser.setName(user.getName());
existingUser.setEmail(user.getEmail());
return userRepository.save(existingUser);
}
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userRepository.deleteById(id);
}
}
接口文档编写(如Swagger)
Swagger(现称OpenAPI)是一种用于描述、生成和操作RESTful网络服务的框架。
使用Swagger注解
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
@Api(value = "User Management API", description = "Operations related to users")
public class UserController {
@GetMapping("/users")
@ApiOperation(value = "Get all users", notes = "Returns a list of all users")
public List<User> getUsers() {
return userRepository.findAll();
}
@GetMapping("/users/{id}")
@ApiOperation(value = "Get user by ID", notes = "Returns a user based on the ID")
public User getUser(@PathVariable Long id) {
return userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException(id));
}
@PostMapping("/users")
@ApiOperation(value = "Create a new user", notes = "Creates a new user")
public User createUser(@RequestBody User user) {
return userRepository.save(user);
}
@PutMapping("/users/{id}")
@ApiOperation(value = "Update a user", notes = "Updates an existing user")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
User existingUser = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException(id));
existingUser.setName(user.getName());
existingUser.setEmail(user.getEmail());
return userRepository.save(existingUser);
}
@DeleteMapping("/users/{id}")
@ApiOperation(value = "Delete a user", notes = "Deletes an existing user")
public void deleteUser(@PathVariable Long id) {
userRepository.deleteById(id);
}
}
安全认证(如JWT)
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间安全地将信息作为JSON对象传输。
使用JWT认证
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private UserDetailsService userDetailsService;
private PasswordEncoder passwordEncoder;
public JwtAuthenticationFilter(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String username = request.getParameter("username");
String password = request.getParameter("password");
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("Invalid credentials");
}
return new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>());
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
User user = (User) authResult.getPrincipal();
String token = generateToken(user.getUsername());
response.addHeader("Authorization", "Bearer " + token);
}
private String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
.signWith(SignatureAlgorithm.HS256, "secret")
.compact();
}
}
日志记录与异常处理
日志记录
使用SLF4J和Logback进行日志记录。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Example {
private static final Logger logger = LoggerFactory.getLogger(Example.class);
public void someMethod() {
logger.info("This is an info message");
logger.error("This is an error message");
}
}
异常处理
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
单元测试与自动化测试
单元测试
使用JUnit和Mockito进行单元测试。
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class UserControllerTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserController userController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetUser() {
User user = new User();
user.setId(1L);
user.setName("Alice");
user.setEmail("alice@example.com");
when(userRepository.findById(1L)).thenReturn(java.util.Optional.of(user));
User result = userController.getUser(1L);
assertEquals("Alice", result.getName());
assertEquals("alice@example.com", result.getEmail());
}
}
自动化测试
使用Spring Boot Test和Spring Boot WebTestClient进行自动化测试。
import static org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction;
import static org.springframework.test.web.reactive.server.returnResult;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class UserControllerTest {
@Test
public void testCreateUser() {
RouterFunction<ServerResponse> routerFunction = userController.routes();
String requestBody = "{\"name\": \"Alice\", \"email\": \"alice@example.com\"}";
bindToRouterFunction(routerFunction)
.post()
.uri("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody)
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.consumeWith(result -> {
assertEquals("{\"name\":\"Alice\",\"email\":\"alice@example.com\"}", result.getResponseBody());
});
}
}
Java前端技术基础
前端框架(如React或Vue.js)
React简介
React是一个开源的JavaScript库,用于构建用户界面,尤其适合构建单页面应用。
Vue简介
Vue是一个开源的JavaScript框架,用于构建用户界面,尤其适合构建单页面应用。
前后端分离开发
前后端分离开发将前端和后端分开,前端专注于用户界面,后端专注于数据处理和逻辑实现。
示例
前端使用React,后端使用Spring Boot。
// React前端代码示例
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get('http://localhost:8080/api/users')
.then(response => setUsers(response.data))
.catch(error => console.error(error));
}, []);
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
export default App;
// Spring Boot后端代码示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api")
public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping("/users")
public List<User> getUsers() {
return userRepository.findAll();
}
}
数据交互与Ajax
使用Ajax
function loadUsers() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:8080/api/users", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var users = JSON.parse(xhr.responseText);
var ul = document.getElementById("users");
ul.innerHTML = "";
for (var i = 0; i < users.length; i++) {
var li = document.createElement("li");
li.textContent = users[i].name + " - " + users[i].email;
ul.appendChild(li);
}
}
};
xhr.send();
}
前端路由与状态管理
前端路由
前端路由允许单页面应用动态加载页面内容,而不需要重新加载整个页面。
// React Router示例
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/user/:id" element={<User />} />
</Routes>
</Router>
);
}
function Home() {
return <h1>Home Page</h1>;
}
function User() {
return <h1>User Page</h1>;
}
export default App;
状态管理
状态管理用于管理前端应用的状态,常见的状态管理库有Redux和MobX。
// Redux示例
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUsers } from './actions';
function App() {
const dispatch = useDispatch();
const users = useSelector(state => state.users);
useEffect(() => {
dispatch(fetchUsers());
}, [dispatch]);
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
export default App;
实战项目与部署
项目需求分析
项目需求分析是项目开发的第一步,需要明确项目的功能需求、性能需求、安全性需求等。
示例
假设开发一个用户管理系统,需求如下:
- 用户登录、注册、修改密码功能。
- 用户信息管理(查看、编辑、删除)。
- 后台管理功能(管理员查看所有用户信息)。
项目架构设计
项目架构设计指定了项目的整体结构和主要组成部分。
示例
- 前端:React
- 后端:Spring Boot
- 数据库:MySQL
- 服务器:Tomcat
项目编码与调试
编码和调试是项目开发的核心步骤,需要编写高质量的代码并进行充分的测试。
示例
// Spring Boot后端代码示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping("/users")
public List<User> getUsers() {
return userRepository.findAll();
}
}
// React前端代码示例
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get('http://localhost:8080/api/users')
.then(response => setUsers(response.data))
.catch(error => console.error(error));
}, []);
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
export default App;
项目测试与部署
项目测试是确保代码质量的重要步骤,项目部署是将项目部署到生产环境的过程。
测试
import static org.springframework.test.web.reactive.server.returnResult;
import org.junit.jupiter.api.Test;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
public class UserControllerTest {
@Test
public void testGetUsers() {
RouterFunction<ServerResponse> routerFunction = userController.routes();
bindToRouterFunction(routerFunction)
.get()
.uri("/api/users")
.exchange()
.expectStatus().isOk()
.expectBodyList(User.class)
.consumeWith(result -> {
for (User user : result.getResponseBody()) {
System.out.println(user.getName());
}
});
}
}
部署
将项目部署到服务器,可以使用Docker容器来部署,也可以使用云服务提供商(如AWS、Azure)来部署。
# 使用Docker部署
docker build -t myapp .
docker run -p 8080:8080 myapp
项目上线与运维
项目上线后需要进行运维,确保系统的稳定性、安全性和性能。
运维
运维包括监控系统、备份数据、更新软件、处理故障等。
# 使用Prometheus监控
apt-get update
apt-get install prometheus
systemctl start prometheus
systemctl enable prometheus
结语
本文详细介绍了Java全栈开发的相关知识,从Java基础到Web开发,再到前端技术,最后到实战项目与部署。希望读者通过本文能够掌握Java全栈开发的基本技能。如果你需要更深入的学习,可以参考慕课网的相关课程。
共同学习,写下你的评论
评论加载中...
作者其他优质文章