本文目录导读:

我来为您介绍一个完整的Java注册功能实现案例,包含前后端交互。
后端实现(Spring Boot)
实体类
// User.java
package com.example.demo.entity;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
private String email;
private String phone;
@Column(name = "create_time")
private LocalDateTime createTime;
// getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public LocalDateTime getCreateTime() { return createTime; }
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
}
DTO(数据传输对象)
// RegisterRequest.java
package com.example.demo.dto;
import javax.validation.constraints.*;
public class RegisterRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度3-20个字符")
@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "用户名只能包含字母、数字和下划线")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度6-20个字符")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
// getters and setters
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
}
响应类
// ApiResponse.java
package com.example.demo.dto;
public class ApiResponse<T> {
private int code;
private String message;
private T data;
public ApiResponse(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(200, "success", data);
}
public static <T> ApiResponse<T> error(int code, String message) {
return new ApiResponse<>(code, message, null);
}
// getters
public int getCode() { return code; }
public String getMessage() { return message; }
public T getData() { return data; }
}
Repository层
// UserRepository.java
package com.example.demo.repository;
import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
boolean existsByUsername(String username);
boolean existsByEmail(String email);
boolean existsByPhone(String phone);
}
Service层
// UserService.java
package com.example.demo.service;
import com.example.demo.dto.RegisterRequest;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
/**
* 用户注册
*/
public User register(RegisterRequest request) {
// 检查用户名是否已存在
if (userRepository.existsByUsername(request.getUsername())) {
throw new RuntimeException("用户名已存在");
}
// 检查邮箱是否已存在
if (request.getEmail() != null && userRepository.existsByEmail(request.getEmail())) {
throw new RuntimeException("邮箱已被注册");
}
// 检查手机号是否已存在
if (request.getPhone() != null && userRepository.existsByPhone(request.getPhone())) {
throw new RuntimeException("手机号已被注册");
}
// 创建新用户
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword())); // 密码加密
user.setEmail(request.getEmail());
user.setPhone(request.getPhone());
user.setCreateTime(LocalDateTime.now());
return userRepository.save(user);
}
}
Controller层
// UserController.java
package com.example.demo.controller;
import com.example.demo.dto.ApiResponse;
import com.example.demo.dto.RegisterRequest;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/user")
@CrossOrigin(origins = "*") // 允许跨域
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public ResponseEntity<ApiResponse<User>> register(@Valid @RequestBody RegisterRequest request) {
try {
User user = userService.register(request);
return ResponseEntity.ok(ApiResponse.success(user));
} catch (RuntimeException e) {
return ResponseEntity.badRequest()
.body(ApiResponse.error(400, e.getMessage()));
}
}
}
安全配置
// SecurityConfig.java
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
前端实现(HTML + JavaScript)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">用户注册</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.register-container {
background: white;
border-radius: 10px;
padding: 40px;
width: 400px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
color: #333;
margin-bottom: 30px;
font-size: 28px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-size: 14px;
font-weight: 500;
}
input {
width: 100%;
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s;
}
input:focus {
outline: none;
border-color: #667eea;
}
input.error {
border-color: #e74c3c;
}
.error-message {
color: #e74c3c;
font-size: 12px;
margin-top: 5px;
display: none;
}
.error-message.show {
display: block;
}
button {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s;
}
button:hover {
transform: translateY(-2px);
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.message {
margin-top: 20px;
padding: 10px;
border-radius: 5px;
display: none;
}
.message.success {
display: block;
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
display: block;
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.password-strength {
height: 5px;
margin-top: 5px;
border-radius: 3px;
transition: all 0.3s;
}
.password-strength.weak {
width: 33%;
background: #e74c3c;
}
.password-strength.medium {
width: 66%;
background: #f39c12;
}
.password-strength.strong {
width: 100%;
background: #27ae60;
}
</style>
</head>
<body>
<div class="register-container">
<h2>用户注册</h2>
<form id="registerForm">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" name="username"
placeholder="3-20位字母、数字或下划线" required>
<div class="error-message" id="usernameError"></div>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password"
placeholder="6-20位字符" required>
<div class="password-strength" id="passwordStrength"></div>
<div class="error-message" id="passwordError"></div>
</div>
<div class="form-group">
<label for="confirmPassword">确认密码</label>
<input type="password" id="confirmPassword" name="confirmPassword"
placeholder="再次输入密码" required>
<div class="error-message" id="confirmPasswordError"></div>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" id="email" name="email"
placeholder="请输入邮箱地址">
<div class="error-message" id="emailError"></div>
</div>
<div class="form-group">
<label for="phone">手机号</label>
<input type="tel" id="phone" name="phone"
placeholder="请输入11位手机号">
<div class="error-message" id="phoneError"></div>
</div>
<button type="submit" id="submitBtn">注册</button>
</form>
<div class="message" id="message"></div>
</div>
<script>
// 获取DOM元素
const form = document.getElementById('registerForm');
const username = document.getElementById('username');
const password = document.getElementById('password');
const confirmPassword = document.getElementById('confirmPassword');
const email = document.getElementById('email');
const phone = document.getElementById('phone');
const submitBtn = document.getElementById('submitBtn');
const message = document.getElementById('message');
// 实时验证
username.addEventListener('blur', validateUsername);
password.addEventListener('input', validatePassword);
confirmPassword.addEventListener('blur', validateConfirmPassword);
email.addEventListener('blur', validateEmail);
phone.addEventListener('blur', validatePhone);
// 密码强度检测
password.addEventListener('input', function() {
const strength = document.getElementById('passwordStrength');
const value = this.value;
if (value.length === 0) {
strength.className = 'password-strength';
return;
}
let score = 0;
if (value.length >= 6) score++;
if (value.length >= 10) score++;
if (/[a-z]/.test(value)) score++;
if (/[A-Z]/.test(value)) score++;
if (/[0-9]/.test(value)) score++;
if (/[^a-zA-Z0-9]/.test(value)) score++;
if (score <= 2) {
strength.className = 'password-strength weak';
} else if (score <= 4) {
strength.className = 'password-strength medium';
} else {
strength.className = 'password-strength strong';
}
});
// 验证用户名
function validateUsername() {
const error = document.getElementById('usernameError');
const value = username.value;
if (!value) {
showError(username, error, '用户名不能为空');
return false;
}
if (!/^[a-zA-Z0-9_]{3,20}$/.test(value)) {
showError(username, error, '用户名格式不正确(3-20位字母、数字或下划线)');
return false;
}
hideError(username, error);
return true;
}
// 验证密码
function validatePassword() {
const error = document.getElementById('passwordError');
const value = password.value;
if (!value) {
showError(password, error, '密码不能为空');
return false;
}
if (value.length < 6 || value.length > 20) {
showError(password, error, '密码长度需在6-20位之间');
return false;
}
hideError(password, error);
return true;
}
// 验证确认密码
function validateConfirmPassword() {
const error = document.getElementById('confirmPasswordError');
const value = confirmPassword.value;
if (!value) {
showError(confirmPassword, error, '请确认密码');
return false;
}
if (value !== password.value) {
showError(confirmPassword, error, '两次密码不一致');
return false;
}
hideError(confirmPassword, error);
return true;
}
// 验证邮箱
function validateEmail() {
const error = document.getElementById('emailError');
const value = email.value;
if (!value) return true; // 邮箱可选
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
showError(email, error, '邮箱格式不正确');
return false;
}
hideError(email, error);
return true;
}
// 验证手机号
function validatePhone() {
const error = document.getElementById('phoneError');
const value = phone.value;
if (!value) return true; // 手机号可选
if (!/^1[3-9]\d{9}$/.test(value)) {
showError(phone, error, '手机号格式不正确');
return false;
}
hideError(phone, error);
return true;
}
// 显示错误
function showError(input, errorElement, message) {
input.classList.add('error');
errorElement.textContent = message;
errorElement.classList.add('show');
}
// 隐藏错误
function hideError(input, errorElement) {
input.classList.remove('error');
errorElement.textContent = '';
errorElement.classList.remove('show');
}
// 提交表单
form.addEventListener('submit', async function(e) {
e.preventDefault();
// 验证所有字段
const isUsernameValid = validateUsername();
const isPasswordValid = validatePassword();
const isConfirmPasswordValid = validateConfirmPassword();
const isEmailValid = validateEmail();
const isPhoneValid = validatePhone();
if (!isUsernameValid || !isPasswordValid || !isConfirmPasswordValid ||
!isEmailValid || !isPhoneValid) {
return;
}
// 准备请求数据
const data = {
username: username.value,
password: password.value,
email: email.value || null,
phone: phone.value || null
};
// 禁用按钮,显示加载状态
submitBtn.disabled = true;
submitBtn.textContent = '注册中...';
message.className = 'message';
try {
const response = await fetch('http://localhost:8080/api/user/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (response.ok && result.code === 200) {
showMessage('注册成功!正在跳转到登录页面...', 'success');
setTimeout(() => {
window.location.href = '/login.html';
}, 2000);
} else {
showMessage(result.message || '注册失败', 'error');
}
} catch (error) {
showMessage('网络错误,请稍后重试', 'error');
console.error('注册错误:', error);
} finally {
submitBtn.disabled = false;
submitBtn.textContent = '注册';
}
});
// 显示消息
function showMessage(text, type) {
message.textContent = text;
message.className = `message ${type}`;
// 3秒后自动隐藏成功消息
if (type === 'success') {
setTimeout(() => {
message.className = 'message';
}, 3000);
}
}
</script>
</body>
</html>
application.yml配置
# application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf-8
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
依赖配置
<!-- pom.xml 关键依赖 -->
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 数据验证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 密码加密 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
</dependencies>
测试用例
// UserServiceTest.java
@SpringBootTest
@AutoConfigureMockMvc
class UserServiceTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@BeforeEach
void setUp() {
userRepository.deleteAll();
}
@Test
void testRegisterSuccess() throws Exception {
String requestBody = "{\"username\":\"testuser\",\"password\":\"123456\"," +
"\"email\":\"test@example.com\",\"phone\":\"13800138000\"}";
mockMvc.perform(post("/api/user/register")
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
@Test
void testRegisterDuplicateUsername() throws Exception {
// 先注册一个用户
User existingUser = new User();
existingUser.setUsername("testuser");
existingUser.setPassword("password");
userRepository.save(existingUser);
String requestBody = "{\"username\":\"testuser\",\"password\":\"123456\"}";
mockMvc.perform(post("/api/user/register")
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.message").value("用户名已存在"));
}
}
这个注册功能案例包括了:
-
后端实现:
- 实体类设计
- 数据验证
- 密码加密
- 异常处理
- RESTful API
-
前端实现:
- 表单验证
- 实时密码强度检测
- AJAX请求
- 用户友好的错误提示
-
安全考虑:
- 密码加密存储
- 输入验证
- 防止SQL注入
- 跨域配置
-
用户体验:
- 实时验证反馈
- 密码强度指示器
- 加载状态提示
- 错误信息友好显示
运行项目后,访问 http://localhost:8080/register.html 即可测试注册功能。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播