Spring Boot企业级应用开发详解

1. 企业级应用概述

企业级应用开发需要考虑更多的因素,包括可扩展性、可维护性、安全性、性能、监控等。Spring Boot为企业级应用开发提供了完整的解决方案。

1.1 企业级应用特点

  • 高可用性:7x24小时稳定运行
  • 高性能:支持高并发和大数据量处理
  • 可扩展性:支持水平扩展和垂直扩展
  • 安全性:完善的安全机制和权限控制
  • 可维护性:清晰的架构和代码规范
  • 监控运维:完善的监控和运维体系

1.2 企业级架构

  • 分层架构:表现层、业务层、数据层
  • 微服务架构:服务拆分、服务治理、服务监控
  • 领域驱动设计:业务建模、领域服务、聚合根
  • 事件驱动架构:异步处理、事件溯源、CQRS

1.3 核心依赖

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring Boot Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
    <!-- Spring Boot Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <!-- Spring Boot Cache -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    
    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    <!-- Spring Boot Validation -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
</dependencies>

2. 企业级架构设计

2.1 分层架构

package com.example.demo.architecture;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = {
    "com.example.demo.controller",
    "com.example.demo.service",
    "com.example.demo.repository",
    "com.example.demo.config"
})
@EnableAspectJAutoProxy
public class EnterpriseArchitectureConfig {
    
    @Bean
    public ApplicationContextAware applicationContextAware() {
        return new ApplicationContextAware();
    }
}

2.2 领域驱动设计

package com.example.demo.domain;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

// 聚合根
@Entity
@Table(name = "orders")
public class Order {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String orderNumber;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private OrderStatus status;
    
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrderItem> items = new ArrayList<>();
    
    @Column(name = "created_at", nullable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    // 业务方法
    public void addItem(OrderItem item) {
        if (status != OrderStatus.DRAFT) {
            throw new IllegalStateException("只能向草稿订单添加商品");
        }
        item.setOrder(this);
        items.add(item);
    }
    
    public void confirm() {
        if (status != OrderStatus.DRAFT) {
            throw new IllegalStateException("只能确认草稿订单");
        }
        if (items.isEmpty()) {
            throw new IllegalStateException("订单必须包含商品");
        }
        status = OrderStatus.CONFIRMED;
        updatedAt = LocalDateTime.now();
    }
    
    public void cancel() {
        if (status == OrderStatus.SHIPPED || status == OrderStatus.DELIVERED) {
            throw new IllegalStateException("已发货或已送达的订单不能取消");
        }
        status = OrderStatus.CANCELLED;
        updatedAt = LocalDateTime.now();
    }
    
    // 枚举
    public enum OrderStatus {
        DRAFT, CONFIRMED, PAID, SHIPPED, DELIVERED, CANCELLED
    }
    
    // 构造方法、getter和setter方法
    public Order() {}
    
    public Order(String orderNumber) {
        this.orderNumber = orderNumber;
        this.status = OrderStatus.DRAFT;
        this.createdAt = LocalDateTime.now();
    }
    
    // getter和setter方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getOrderNumber() { return orderNumber; }
    public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; }
    
    public OrderStatus getStatus() { return status; }
    public void setStatus(OrderStatus status) { this.status = status; }
    
    public List<OrderItem> getItems() { return items; }
    public void setItems(List<OrderItem> items) { this.items = items; }
    
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
    
    public LocalDateTime getUpdatedAt() { return updatedAt; }
    public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
}

2.3 领域服务

package com.example.demo.domain.service;

import com.example.demo.domain.Order;
import com.example.demo.domain.OrderItem;
import com.example.demo.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
@Transactional
public class OrderDomainService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    // 创建订单
    public Order createOrder(String orderNumber) {
        Order order = new Order(orderNumber);
        return orderRepository.save(order);
    }
    
    // 添加商品到订单
    public void addItemToOrder(Long orderId, OrderItem item) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        order.addItem(item);
        orderRepository.save(order);
    }
    
    // 确认订单
    public void confirmOrder(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        order.confirm();
        orderRepository.save(order);
    }
    
    // 取消订单
    public void cancelOrder(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        order.cancel();
        orderRepository.save(order);
    }
    
    // 查询用户订单
    public List<Order> getUserOrders(Long userId) {
        return orderRepository.findByUserId(userId);
    }
}

3. 企业级安全

3.1 安全配置

package com.example.demo.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class EnterpriseSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/api/public/**").permitAll()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();
    }
}

3.2 权限控制

package com.example.demo.security;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class SecureBusinessService {
    
    // 基于角色的权限控制
    @PreAuthorize("hasRole('ADMIN')")
    public void adminOnlyOperation() {
        // 只有管理员可以执行的操作
    }
    
    // 基于表达式的权限控制
    @PreAuthorize("hasRole('USER') and #userId == authentication.principal.id")
    public void userSpecificOperation(Long userId) {
        // 用户只能操作自己的数据
    }
    
    // 基于方法的权限控制
    @PreAuthorize("hasPermission(#orderId, 'Order', 'READ')")
    public Order getOrder(Long orderId) {
        // 基于权限的订单查询
        return null;
    }
    
    // 基于数据的权限控制
    @PreAuthorize("hasRole('ADMIN') or @orderService.isOwner(#orderId, authentication.principal.id)")
    public void updateOrder(Long orderId, Order order) {
        // 管理员或订单所有者可以更新订单
    }
}

4. 企业级数据管理

4.1 多数据源配置

package com.example.demo.config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.demo.repository.primary",
    entityManagerFactoryRef = "primaryEntityManagerFactory",
    transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDataSourceConfig {
    
    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Primary
    @Bean(name = "primaryEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
            @Qualifier("primaryDataSource") DataSource dataSource) {
        
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.example.demo.entity.primary");
        
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        properties.setProperty("hibernate.show_sql", "false");
        em.setJpaProperties(properties);
        
        return em;
    }
    
    @Primary
    @Bean(name = "primaryTransactionManager")
    public PlatformTransactionManager primaryTransactionManager(
            @Qualifier("primaryEntityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory.getObject());
    }
}

4.2 事务管理

package com.example.demo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Isolation;

@Service
@Transactional
public class EnterpriseTransactionService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    // 只读事务
    @Transactional(readOnly = true)
    public Order getOrder(Long orderId) {
        return orderRepository.findById(orderId).orElse(null);
    }
    
    // 写事务
    @Transactional
    public Order createOrder(Order order) {
        return orderRepository.save(order);
    }
    
    // 新事务
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logOrderCreation(Long orderId) {
        // 记录订单创建日志,使用新事务确保日志记录成功
    }
    
    // 嵌套事务
    @Transactional(propagation = Propagation.NESTED)
    public void updateOrderItems(Long orderId, List<OrderItem> items) {
        // 更新订单商品,使用嵌套事务
    }
    
    // 隔离级别控制
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void updateOrderStatus(Long orderId, OrderStatus status) {
        // 使用读已提交隔离级别
    }
}

5. 企业级缓存

5.1 分布式缓存

package com.example.demo.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

@Service
public class EnterpriseCacheService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 缓存用户信息
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
    
    // 更新缓存
    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        return userRepository.save(user);
    }
    
    // 清除缓存
    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
    
    // 分布式锁
    public boolean acquireLock(String lockKey, String lockValue, long expireTime) {
        Boolean success = redisTemplate.opsForValue()
                .setIfAbsent(lockKey, lockValue, expireTime, TimeUnit.SECONDS);
        return success != null && success;
    }
    
    // 释放锁
    public void releaseLock(String lockKey, String lockValue) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                       "return redis.call('del', KEYS[1]) else return 0 end";
        redisTemplate.execute(script, Collections.singletonList(lockKey), lockValue);
    }
}

5.2 缓存策略

package com.example.demo.cache;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class CacheStrategyService {
    
    // 缓存预热
    @Cacheable(value = "hotData")
    public List<String> getHotData() {
        return getDataFromDatabase();
    }
    
    // 缓存更新策略
    @Caching(
        evict = {
            @CacheEvict(value = "users", key = "#user.id"),
            @CacheEvict(value = "userList", allEntries = true)
        }
    )
    public User updateUser(User user) {
        return userRepository.save(user);
    }
    
    // 缓存穿透防护
    @Cacheable(value = "users", key = "#id", unless = "#result == null")
    public User getUserById(Long id) {
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            // 缓存空值,防止缓存穿透
            return new User();
        }
        return user;
    }
    
    private List<String> getDataFromDatabase() {
        // 从数据库获取数据
        return null;
    }
}

6. 企业级监控

6.1 监控配置

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: "*"
      base-path: /actuator
  endpoint:
    health:
      show-details: always
      show-components: always
    info:
      enabled: true
  health:
    defaults:
      enabled: true
    diskspace:
      threshold: 100MB
    db:
      enabled: true
  metrics:
    export:
      prometheus:
        enabled: true
    distribution:
      percentiles-histogram:
        http.server.requests: true
      percentiles:
        http.server.requests: 0.5, 0.95, 0.99

6.2 自定义监控

package com.example.demo.monitoring;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicLong;

@Component
public class EnterpriseMonitor {
    
    private final Counter businessCounter;
    private final Timer businessTimer;
    private final AtomicLong activeUsers;
    
    @Autowired
    public EnterpriseMonitor(MeterRegistry meterRegistry) {
        this.businessCounter = Counter.builder("business.operations")
                .description("Business operations count")
                .register(meterRegistry);
        
        this.businessTimer = Timer.builder("business.processing.time")
                .description("Business processing time")
                .register(meterRegistry);
        
        this.activeUsers = meterRegistry.gauge("business.active.users", new AtomicLong(0));
    }
    
    public void recordBusinessOperation() {
        businessCounter.increment();
    }
    
    public void recordProcessingTime(Runnable operation) {
        businessTimer.record(operation);
    }
    
    public void setActiveUsers(long count) {
        activeUsers.set(count);
    }
}

7. 企业级部署

7.1 Docker配置

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY target/enterprise-app-1.0.0.jar app.jar

EXPOSE 8080

ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC"

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

7.2 Kubernetes配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: enterprise-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: enterprise-app
  template:
    metadata:
      labels:
        app: enterprise-app
    spec:
      containers:
      - name: enterprise-app
        image: enterprise-app:latest
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: enterprise-app-service
spec:
  selector:
    app: enterprise-app
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

8. 企业级最佳实践

8.1 代码规范

package com.example.demo.bestpractice;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;

@Service
@Transactional
public class EnterpriseBestPracticeService {
    
    // 1. 使用Optional处理空值
    public Optional<User> findUserById(Long id) {
        return userRepository.findById(id);
    }
    
    // 2. 使用Builder模式构建复杂对象
    public Order createOrder(OrderBuilder builder) {
        return builder
                .setOrderNumber(generateOrderNumber())
                .setStatus(OrderStatus.DRAFT)
                .setCreatedAt(LocalDateTime.now())
                .build();
    }
    
    // 3. 使用策略模式处理不同业务逻辑
    public void processOrder(Order order, PaymentStrategy strategy) {
        strategy.processPayment(order);
    }
    
    // 4. 使用事件驱动架构
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 处理订单创建事件
    }
    
    // 5. 使用AOP处理横切关注点
    @AuditLog
    public void updateUser(User user) {
        userRepository.save(user);
    }
}

8.2 配置管理

# application.yml
spring:
  application:
    name: enterprise-app
  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}
  
  datasource:
    url: ${DB_URL:jdbc:mysql://localhost:3306/enterprise}
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD:password}
    hikari:
      maximum-pool-size: ${DB_MAX_POOL_SIZE:20}
      minimum-idle: ${DB_MIN_IDLE:5}
  
  cache:
    type: ${CACHE_TYPE:redis}
    redis:
      time-to-live: ${CACHE_TTL:600000}
  
  security:
    jwt:
      secret: ${JWT_SECRET:mySecretKey}
      expiration: ${JWT_EXPIRATION:86400}

server:
  port: ${SERVER_PORT:8080}
  servlet:
    context-path: ${CONTEXT_PATH:/api}

logging:
  level:
    root: ${LOG_LEVEL:INFO}
    com.example.demo: ${APP_LOG_LEVEL:DEBUG}
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

9. 总结

Spring Boot企业级应用开发需要综合考虑多个方面:

  1. 架构设计:分层架构、领域驱动设计、微服务架构
  2. 安全机制:认证授权、权限控制、数据安全
  3. 数据管理:多数据源、事务管理、数据一致性
  4. 缓存策略:分布式缓存、缓存一致性、缓存性能
  5. 监控运维:应用监控、性能监控、日志监控
  6. 部署运维:容器化部署、Kubernetes编排、自动化运维
  7. 最佳实践:代码规范、配置管理、性能优化

通过系统性的企业级应用开发,可以构建出高质量、高性能、高可用的Spring Boot应用。


核心功能 文章/图片/视频发布、喜欢、统计阅读次数。 文章标签tag功能、支持按tag分类 文章支持ueditor/markdown编辑器切换(后台配置) 评论功能,支持回复,支持表情。 第三方(微博、QQ)登录。 lucene实现的站内搜索。 响应式布局 支持用户订阅 先看效果图 SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) http://localhost:8080/admin/group/list SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能)SpringBoot开发非常美观的java博客系统(包含后台管理功能) 技术选型: JDK8 数据库MySQL 主框架 (Spring-bootSpring-data-jpa) 安全权限 Shiro 搜索工具 Lucene 缓存 Ehcache 视图模板 Freemarker 其它 Jsoup、fastjson jQuery、Seajs Bootstrap 前端框架 UEditor/Markdown编辑器 font-Awesome 字体/图标 准备工作(sql文件在项目里面) 安装 Jdk8 安装 Maven 准备 IDE (如果你不看源码,可以忽略下面的步骤,直接通过Maven编译war包:mvn clean package -DskipTests) IDE 需要配置的东西 编码方式设为UTF-8 配置Maven 设置Jdk8 关于这些配置,网上有一大把的资料,所以此处不再重复。 获取代码导入到IDE 下载代码 导入到IDE的时候请选择以Maven的方式导入 项目配置参考 系统配置手册 配置完毕 启动项目,在控制台看到Mblog加载完毕的信息后,表示启动成功 打开浏览器输入:http//localhost/mblog/ (此处仅是示例,具体具体端口因人而异),访问成功即部署完毕 后台管理的地址是 /admin, 如果你是管理员账号点导航栏的头像会看到"后台管理" 启动成功后,你应该去后台的系统配置里配置你的网站信息等。 常见问题总结 进入系统后, 菜单加载不出来, 那应该是你没有导 db_init.sql 点标签显示乱码, 请设置Tomcat的 URIEncoding 为 UTF-8 项目截图 SpringBoot开发非常美观的java博客系统(包含后台管理功能) 转自:https://gitee.com/mtons/mblog SpringBoot开发非常美观的java博客系统(包含后台管理功能) 注意: 一、java main方式运行mblog-web下的BootApplication.java时抛出异常的解决方案 Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. SpringBoot开发非常美观的java博客系统(包含后台管理功能) 注释掉后下面图片的这段后,记得maven要重新reimport SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) 否则maven依赖不生效还是会抛出以上的异常 二、第三方登录点击后无响应,那是因为第三方开放平台回调的url失效导致,需要你去对应的第三方开放平台注册app后获取对应的oauth帐号 SpringBoot开发非常美观的java博客系统(包含后台管理功能) 三、idea以maven项目导入该项目后,发现没有maven的依赖包时,需要对每个maven module进行clear和install,并且注意maven的依赖顺序 SpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能) 四、访问地址是http://localhost:8080 登录时,帐号,密码只要自己找个密码,然后md5下在更新到db中即可登录成功。 比如:zuidaima 111111,md5后密码是 3931MUEQD1939MQMLM4AISPVNE,md5的javaSpringBoot开发非常美观的java博客系统(包含后台管理功能) SpringBoot开发非常美观的java博客系统(包含后台管理功能)
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小凯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值