技术选型与架构设计

后端采用Spring Boot框架,简化配置并提供RESTful API支持。数据库使用MySQL 8.0,利用其JSON功能和事务特性。前端可选Vue.js或React,通过Axios与后端交互。采用微服务架构分离核心模块:案件分类服务、律师匹配服务、用户管理服务。

数据库设计

-- 用户表(包含律师标记)
CREATE TABLE `user` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `username` VARCHAR(50) UNIQUE,
  `password` VARCHAR(100),
  `role` ENUM('client', 'lawyer', 'admin'),
  `specialization` VARCHAR(100), -- 律师专长领域
  `rating` DECIMAL(3,2) DEFAULT 0.0
);

-- 案件分类表
CREATE TABLE `case_category` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(50) UNIQUE,
  `keywords` JSON -- 存储分类关键词数组
);

-- 案件表
CREATE TABLE `legal_case` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
  `client_id` BIGINT,
  `title` VARCHAR(200),
  `description` TEXT,
  `category_id` INT,
  `status` ENUM('pending', 'matched', 'closed'),
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (`client_id`) REFERENCES `user`(`id`),
  FOREIGN KEY (`category_id`) REFERENCES `case_category`(`id`)
);

-- 律师匹配记录
CREATE TABLE `case_assignment` (
  `case_id` BIGINT,
  `lawyer_id` BIGINT,
  `match_score` DECIMAL(5,2),
  `assigned_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`case_id`, `lawyer_id`),
  FOREIGN KEY (`case_id`) REFERENCES `legal_case`(`id`),
  FOREIGN KEY (`lawyer_id`) REFERENCES `user`(`id`)
);

案件分类实现

采用TF-IDF算法结合预定义分类规则:

// 分类服务实现
@Service
public class CaseClassifier {
    @Autowired
    private CaseCategoryRepository categoryRepo;

    public CaseCategory classifyCase(String description) {
        List<CaseCategory> categories = categoryRepo.findAll();
        Map<CaseCategory, Double> scores = new HashMap<>();
        
        // 预处理文本
        String processedText = TextProcessor.process(description);
        
        // 计算TF-IDF得分
        for (CaseCategory category : categories) {
            double score = calculateSimilarity(processedText, category.getKeywords());
            scores.put(category, score);
        }
        
        return Collections.max(scores.entrySet(), 
            Comparator.comparingDouble(Map.Entry::getValue)).getKey();
    }
    
    private double calculateSimilarity(String text, JSONArray keywords) {
        // 实现关键词匹配算法
    }
}

律师匹配算法

基于多维度的匹配策略:

@Service
public class LawyerMatcher {
    @Autowired
    private UserRepository userRepo;

    public List<User> matchLawyers(Long caseId, Integer categoryId) {
        LegalCase legalCase = caseRepo.findById(caseId).orElseThrow();
        List<User> lawyers = userRepo.findBySpecializationAndRole(
            legalCase.getCategory().getName(), "lawyer");
            
        return lawyers.stream()
            .map(lawyer -> {
                double score = calculateMatchScore(legalCase, lawyer);
                return new AbstractMap.SimpleEntry<>(lawyer, score);
            })
            .sorted((e1, e2) -> Double.compare(e2.getValue(), e1.getValue()))
            .limit(5)
            .map(AbstractMap.SimpleEntry::getKey)
            .collect(Collectors.toList());
    }
    
    private double calculateMatchScore(LegalCase legalCase, User lawyer) {
        // 专业领域匹配度
        double specializationScore = calculateSpecializationMatch(
            legalCase.getCategory(), lawyer.getSpecialization());
        
        // 律师评分系数
        double ratingScore = lawyer.getRating() * 0.2;
        
        // 案件复杂度匹配(可选)
        double complexityScore = calculateComplexityMatch(
            legalCase.getDescription().length());
            
        return specializationScore * 0.6 + ratingScore * 0.3 + complexityScore * 0.1;
    }
}

RESTful API设计

@RestController
@RequestMapping("/api/cases")
public class CaseController {
    @Autowired
    private CaseService caseService;

    @PostMapping
    public ResponseEntity<LegalCase> createCase(
        @RequestBody CaseRequest request, 
        @AuthenticationPrincipal User user) {
        LegalCase legalCase = caseService.createCase(user, request);
        return ResponseEntity.created(URI.create("/cases/" + legalCase.getId()))
            .body(legalCase);
    }

    @GetMapping("/{id}/matches")
    public ResponseEntity<List<LawyerDTO>> getMatchedLawyers(
        @PathVariable Long id) {
        return ResponseEntity.ok(caseService.findMatchedLawyers(id));
    }
}

// 案件请求DTO
public class CaseRequest {
    @NotBlank
    private String title;
    
    @NotBlank
    @Size(min = 50)
    private String description;
    
    // Getters and Setters
}

系统集成与部署

  1. 使用Docker容器化服务:
# MySQL容器配置
FROM mysql:8.0
ENV MYSQL_ROOT_PASSWORD=complexpassword
COPY init.sql /docker-entrypoint-initdb.d/

  1. Spring Boot应用配置:
# application.yml
spring:
  datasource:
    url: jdbc:mysql://mysql:3306/legal_db
    username: root
    password: complexpassword
  jpa:
    hibernate:
      ddl-auto: validate

  1. 使用Redis缓存高频访问数据:
@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
    }
}

性能优化建议

  1. 案件分类预处理:
  • 使用Elasticsearch建立法律文本索引
  • 实现异步分类处理机制
@Async
public void asyncClassifyCase(Long caseId) {
    // 分类处理逻辑
}

  1. 律师匹配缓存:
  • 缓存律师专业领域数据
  • 实现匹配结果预计算
@Cacheable(value = "lawyerMatches", key = "#caseId")
public List<LawyerDTO> findMatchedLawyers(Long caseId) {
    // 匹配逻辑
}

  1. 数据库优化:
  • 为案件表添加全文索引
ALTER TABLE legal_case ADD FULLTEXT INDEX ft_desc (description);

  • 使用读写分离配置
spring:
  datasource:
    read:
      url: jdbc:mysql://replica:3306/legal_db
    write:
      url: jdbc:mysql://master:3306/legal_db

安全实施方案

  1. JWT认证:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .addFilter(new JwtAuthenticationFilter(authenticationManager()))
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

  1. 数据加密:
@Entity
public class User {
    @Convert(converter = CryptoConverter.class)
    private String phoneNumber;
}

@Converter
public class CryptoConverter implements AttributeConverter<String, String> {
    @Override
    public String convertToDatabaseColumn(String attribute) {
        return AES.encrypt(attribute);
    }
}

  1. 审计日志:
@EntityListeners(AuditingEntityListener.class)
public class LegalCase {
    @CreatedBy
    private String createdBy;
    
    @LastModifiedDate
    private LocalDateTime lastModified;
}

更多推荐