Java 商城后台管理系统

### 构建一个健壮的商城后台管理系统

使用Java Spring Boot框架和MySQL数据库,逐步构建一个健壮、安全、高效的商城后台管理系统。本文涵盖用户管理、商品管理、订单管理、分类管理、权限控制、日志记录、分页和排序、文件上传、缓存以及国际化。

---

#### 项目初始化

首先,我们使用Spring Initializr创建项目,选择以下依赖:
- Spring Web
- Spring Data JPA
- MySQL Driver
- Spring Security
- Spring Boot DevTools

#### 配置文件
在`src/main/resources/application.properties`中配置数据库连接:
```properties
spring.datasource.url=jdbc:mysql://localhost:3306/yourdatabase
spring.datasource.username=yourusername
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
```

---

### 基本功能实现

#### 数据库模型

**用户实体**
```java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String password;
    private String role;

    // getters and setters
}
```

**商品实体**
```java
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private BigDecimal price;
    private String description;
    private String category;

    // getters and setters
}
```

**订单实体**
```java
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long userId;
    private Long productId;
    private Integer quantity;
    private String status;

    // getters and setters
}
```

---

#### Repository接口

**UserRepository**
```java
public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}
```

**ProductRepository**
```java
public interface ProductRepository extends JpaRepository<Product, Long> {
}
```

**OrderRepository**
```java
public interface OrderRepository extends JpaRepository<Order, Long> {
}
```

---

#### 服务层

**UserService**
```java
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public User save(User user) {
        return userRepository.save(user);
    }

    public User findByUsername(String username) {
        return userRepository.findByUsername(username);
    }
}
```

**ProductService**
```java
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    public Product save(Product product) {
        return productRepository.save(product);
    }

    public List<Product> findAll() {
        return productRepository.findAll();
    }
}
```

**OrderService**
```java
@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;

    public Order save(Order order) {
        return orderRepository.save(order);
    }

    public List<Order> findAll() {
        return orderRepository.findAll();
    }
}
```

---

#### 控制器层

**UserController**
```java
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public User register(@RequestBody User user) {
        return userService.save(user);
    }

    @GetMapping("/{username}")
    public User findByUsername(@PathVariable String username) {
        return userService.findByUsername(username);
    }
}
```

**ProductController**
```java
@RestController
@RequestMapping("/products")
public class ProductController {
    @Autowired
    private ProductService productService;

    @PostMapping
    public Product addProduct(@RequestBody Product product) {
        return productService.save(product);
    }

    @GetMapping
    public List<Product> getAllProducts() {
        return productService.findAll();
    }
}
```

**OrderController**
```java
@RestController
@RequestMapping("/orders")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @PostMapping
    public Order createOrder(@RequestBody Order order) {
        return orderService.save(order);
    }

    @GetMapping
    public List<Order> getAllOrders() {
        return orderService.findAll();
    }
}
```

---

### 分类管理

**分类实体**
```java
@Entity
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;

    // getters and setters
}
```

**CategoryRepository**
```java
public interface CategoryRepository extends JpaRepository<Category, Long> {
}
```

**CategoryService**
```java
@Service
public class CategoryService {
    @Autowired
    private CategoryRepository categoryRepository;

    public Category save(Category category) {
        return categoryRepository.save(category);
    }

    public List<Category> findAll() {
        return categoryRepository.findAll();
    }

    public void delete(Long id) {
        categoryRepository.deleteById(id);
    }
}
```

**CategoryController**
```java
@RestController
@RequestMapping("/categories")
public class CategoryController {
    @Autowired
    private CategoryService categoryService;

    @PostMapping
    public Category addCategory(@RequestBody Category category) {
        return categoryService.save(category);
    }

    @GetMapping
    public List<Category> getAllCategories() {
        return categoryService.findAll();
    }

    @DeleteMapping("/{id}")
    public void deleteCategory(@PathVariable Long id) {
        categoryService.delete(id);
    }
}
```

---

### 权限控制

**Spring Security 配置**
```java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/users/register").permitAll()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin().permitAll()
            .and()
            .logout().permitAll();
    }
}
```

**密码编码器配置**
```java
@Configuration
public class WebConfig {
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
```

**修改UserService以实现UserDetailsService**
```java
@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    public User save(User user) {
        user.setPassword(bCryptPasswordEncoder().encode(user.getPassword()));
        return userRepository.save(user);
    }

    public User findByUsername(String username) {
        return userRepository.findByUsername(username);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
                AuthorityUtils.createAuthorityList(user.getRole()));
    }
}
```

---

### 统一异常处理

**自定义异常类**
```java
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}
```

**异常处理器**
```java
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
```

---

### 数据验证

**在实体类中添加验证注解**
```java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    private String username;

    @NotBlank
    @Size(min = 6)
    private String password;

    private String role;

    // getters and setters
}
```

**在控制器方法中进行验证**
```java
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public User register(@Valid @RequestBody User user) {
        return userService.save(user);
    }

    @GetMapping("/{username}")
    public User findByUsername(@PathVariable String username) {
        return userService.findByUsername(username);
    }
}
```

**添加验证错误处理**
```java
@ControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}
```

---

### 日志记录

**添加日志依赖**
在`pom.xml`中添加依赖:
```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>
```

**创建日志配置**
在`src/main/resources/application.properties`中配置日志级别:
```properties
logging.level.root=INFO
logging.level.org.springframework.web=DEBUG
logging.file.name=app.log
```

**在各层添加日志**
例如在`UserService`中添加日志:
```java
@Service
public class UserService implements UserDetailsService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private UserRepository userRepository;

    public User save(User user) {
        logger.info("Saving user: {}", user.getUsername());
        user.setPassword(bCryptPasswordEncoder().encode(user.getPassword()));
        return userRepository.save(user);
    }

    public User findByUsername(String username) {
        logger.info("Finding user by username: {}", username);
        return userRepository.findByUsername(username);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        logger.info("Loading user by username: {}", username);
        User user = userRepository.findByUsername(username);
        if (user == null) {
            logger.error("User not found: {}", username);
            throw new UsernameNotFoundException("User not found");
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
                AuthorityUtils.createAuthorityList(user.getRole()));
    }
}
```

---

### 分页和排序

**在Repository接口中添加分页和排序方法**
```java
public interface ProductRepository extends JpaRepository<Product, Long> {
    Page<Product> findAll(Pageable pageable);
}
```

**在服务层添加分页和排序方法**
```java
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    public Page<Product> findAll(Pageable pageable) {
        return productRepository.findAll(pageable);
    }
}
```

**在控制器层添加分页和排序接口**
```java
@RestController
@RequestMapping("/products")
public class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping
    public Page<Product> getAllProducts(@RequestParam int page, @RequestParam int size) {
        Pageable pageable = PageRequest.of(page, size);
        return productService.findAll(pageable);
    }
}
```

---

### 文件上传

**添加文件上传依赖**
在`pom.xml`中添加依赖:
```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
```

**文件上传配置**
在`src/main/resources/application.properties`中配置文件上传路径:
```properties
spring.servlet.multipart.max-file-size=2MB
spring.servlet.multipart.max-request-size=2MB
file.upload-dir=uploads/
```

**创建文件上传控制器**
```java
@RestController
@RequestMapping("/files")
public class FileController {

    @Value("${file.upload-dir}")
    private String uploadDir;

    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            Path copyLocation = Paths
                .get(uploadDir + File.separator + StringUtils.cleanPath(file.getOriginalFilename()));
            Files.copy(file.getInputStream(), copyLocation, StandardCopyOption.REPLACE_EXISTING);
            return ResponseEntity.ok("File uploaded successfully: " + file.getOriginalFilename());
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Could not upload file: " + file.getOriginalFilename());
        }
    }
}
```

---

### 缓存

**添加缓存依赖**
在`pom.xml`中添加依赖:
```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
```

**配置缓存**
在`src/main/resources/application.properties`中配置Redis:
```properties
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
```

**启用缓存**
在启动类中启用缓存:
```java
@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
```

**在服务层使用缓存**
```java
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;

    @Cacheable("products")
    public List<Product> findAll() {
        return productRepository.findAll();
    }
}
```

---

### 国际化

**配置国际化资源文件**
在`src/main/resources`下创建国际化资源文件,如`messages.properties`和`messages_zh.properties`。

**配置国际化**
在`src/main/resources/application.properties`中配置国际化:
```properties
spring.messages.basename=messages
```

**创建国际化配置类**
```java
@Configuration
public class InternationalizationConfig {

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.US);
        return localeResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("lang");
        return interceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}
```

**在控制器中使用国际化**
```java
@RestController
public class GreetingController {

    @Autowired
    private MessageSource messageSource;

    @GetMapping("/greeting")
    public String greeting(@RequestParam(name = "lang", required = false) String lang) {
        return messageSource.getMessage("greeting.message", null, LocaleContextHolder.getLocale());
    }
}
```

---

通过这些步骤,构建了一个健壮的商城后台管理系统。该系统不仅包括基本的用户、商品和订单管理,还添加了分类管理、权限控制、统一异常处理、数据验证、日志记录、分页和排序、文件上传、缓存和国际化等功能,使系统更加完善和高效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型时代的基础架构,大模型算力中心建设指南重磅来袭!

什么是最畅销商品&#xff1f;什么是高毛利商品&#xff1f; 我们来看一个例子&#xff1a; 一件T恤使用成本为100元的原料&#xff0c;价格为140元。另一件T恤使用成本为80元的原料&#xff0c;但在样式、颜色、图案的设计上比较有特色&#xff0c;价格也为140元。 当这两件…

【JVM-04】线上CPU100%

【JVM-04】线上CPU100% 1. 如何排查2. 再举一个例子 1. 如何排查 ⼀般CPU100%疯狂GC&#xff0c;都是死循环的锅&#xff0c;那怎么排查呢&#xff1f;先进服务器&#xff0c;⽤top -c 命令找出当前进程的运⾏列表按⼀下 P 可以按照CPU使⽤率进⾏排序显示Java进程 PID 为 2609…

苏东坡传-读书笔记七

苏堤和西湖之与杭州&#xff0c;正如美女花容月貌上的双眸。我常想&#xff0c;倘若西湖之是空空的一片水——没有苏堤那秀美的修眉和虹彩般的仙岛&#xff0c;一画龙点睛增其神韵&#xff0c;那西湖该望之如何?几百年来的中国游客&#xff0c;春季到来之时&#xff0c;向西湖…

throw和catch关键字的作用。

在C中&#xff0c;throw和catch是异常处理机制的关键字&#xff0c;它们共同工作以处理在程序执行过程中发生的异常情况。 throw 关键字 throw关键字用于抛出一个异常。当程序遇到无法处理的错误时&#xff0c;它会使用throw语句抛出一个异常。这通常是因为遇到了某些无法恢复…

使用Vue 2 + Element UI搭建后台管理系统框架实战教程

后台管理系统作为企业内部的核心业务平台&#xff0c;其界面的易用性和功能性至关重要。Vue 2作为一个成熟的前端框架&#xff0c;以其轻量级和高效著称&#xff0c;而Element UI则是一套专为桌面端设计的Vue 2组件库&#xff0c;它提供了丰富的UI元素和组件&#xff0c;大大简…

如何在Python中实现一个简单的爬虫程序

如何在Python中实现一个简单的爬虫程序 随着互联网的发展&#xff0c;数据已成为当今社会最宝贵的资源之一。而爬虫程序则成为了获取互联网数据的重要工具之一。本文将介绍如何在Python中实现一个简单的爬虫程序&#xff0c;并提供具体的代码示例。 确定目标网站 在开始编写爬…

【Python】已解决:urllib.error.HTTPError: HTTP Error 403: Forbidden

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;urllib.error.HTTPError: HTTP Error 403: Forbidden 一、分析问题背景 在使用Python的urllib库中的urlopen或urlretrieve函数下载文件时&#xff0c;有时会遇到…

Android动画:提升用户体验的关键技术

Android平台上的动画技术不仅仅是界面美化的手段&#xff0c;它更是提升用户体验、增强交互性和吸引用户注意力的重要工具。从简单的过渡动画到复杂的视图动态效果&#xff0c;Android开发者可以利用丰富的动画API创造出令人印象深刻的应用程序。本文将深入探讨Android动画的多…

Python打字练习

代码解析 导入模块和定义单词列表 import tkinter as tk import randomsample_words ["apple", "banana", "cherry", "date", "fig", "grape", "kiwi", "lemon", "mango", &quo…

LDA主题分析的原理、步骤和实现

当然可以&#xff01;LDA 主题模型是一种强大的工具&#xff0c;用于从大量文本数据中发现隐藏的主题。让我们更详细地介绍它的原理、步骤和实现。 LDA原理 LDA是一种生成模型&#xff0c;它假设&#xff1a; 每个文档是由若干主题组成的。每个主题是由若干词汇组成的。 具…

vcpkg国内镜像源替换

vcpkg国内镜像源替换 一、从Gitee上下载vcpkg二、全局替换vcpkg/scripts文件下的字符三、回到vcpkg目录下&#xff0c;执行bootstrap-vcpkg.bat文件&#xff0c;等待执行完毕四、全局替换vcpkg/ports文件下的字符 一、从Gitee上下载vcpkg git clone https://gitee.com/mirrors…

全国30省份各省资本存量数据固定资本形成总额永续盘存法(2000-2023年)

各省资本存量数据通过永续盘存法进行了详细的计算&#xff0c;这一方法覆盖了中国30个省份&#xff08;不包括西藏&#xff09;&#xff0c;提供从2000年起直至2023的资本存量数据集。包括原始数据、测算过程、最终的资本存量结果。 以2000年作为基期年份&#xff0c;依据…

电路笔记(PCB):电流容量(IPC-2221和IPC-2152)+阻抗匹配

电流容量 IPC-2221经验公式 I K T b A c IK\times T^{b}\times A^{c} IKTbAc 这个公式用于估计PCB&#xff08;Printed Circuit Board&#xff0c;印刷电路板&#xff09;导线上的电流&#xff08;I&#xff09;&#xff0c;其中T和A分别表示温度&#xff08;Temperature&a…

flex布局中子元素内容超出时,子元素本身出现滚动条实现方法

flex布局中子元素宽度平均分配&#xff0c;并且当子元素内容超出时&#xff0c;子元素本身出现滚动条实现方法&#xff1a; 将父元素设置为display: flex&#xff0c;以启用Flexbox布局。将每个子元素的flex属性设置为1&#xff0c;以使其宽度平均分配。设置子元素的overflow属…

toRefs 和 toRef

文章目录 toRefs 和 toReftoRefstoRef toRefs 和 toRef toRefs toRefs 把一个由reactive对象的值变为一个一个ref的响应式的值 import { ref, reactive, toRefs, toRef } from vue; let person reactive({name: 张三,age: 18, }); // toRefs 把一个由reactive对象的值变为一…

ComfyUI流程图、文生图、图生图步骤教学!

前言 leetcode , 209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的子数组 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 …

大厂都在“抢滩”欧洲杯,你该如何蹭上热度?

2024欧洲杯战至第三轮小组赛&#xff0c;德国、瑞士、西班牙、意大利已出线角逐1/8决赛。 云略统计&#xff0c;欧洲杯开战至今&#xff0c;抖音上“欧洲杯”相关话题高达1000个&#xff0c;其中#谁是欧洲杯预言家 话题播放量高达7.57亿&#xff0c;C罗、姆巴佩等国际巨星更是频…

DB-100撕裂开关 JOSEF约瑟 合金接线端子,轻松接线

一、产品概述 型号&#xff1a;DB-100 主要用途&#xff1a;DB-100撕裂开关主要用于监测皮带输送机在运行过程中是否发生纵向撕裂&#xff0c;一旦发现撕裂情况&#xff0c;立即触发报警或停机&#xff0c;以保护设备和生产线的安全运行。 二、技术特点 检测原理&#xff1a;…

Snipaste截图工具的下载

Snipaste是一款简单而强大的桌面截图工具&#xff0c;它不仅支持快速截图&#xff0c;还提供了丰富的编辑和贴图功能&#xff0c;极大地提升了用户的工作效率。 网址&#xff1a;Snipaste 下载 1.进入文件夹解压缩 2.解压缩后打开双击运行 3.快捷键F1截图 F3截图固定桌面 …

springboot的双亲委派

双亲委派模型&#xff08;Parent Delegation Model&#xff09;是 Java 类加载机制中的一种设计模式&#xff0c;用于确保 Java 类加载的一致性和安全性。这个模型规定&#xff0c;当一个类加载器加载一个类时&#xff0c;它首先将加载请求委派给父类加载器处理&#xff0c;只有…