作者:chasel-rain
来自:https://blog.csdn.net/qq_28125445
源码地址:https://download.csdn.net/download/qq_28125445/10322437
关于springboot, 之前零零碎碎地写了一些,今天从项目实战角度给大家分享一下我的一点经验。
话不多说,先从项目的目录结构讲起。
如图:
项目分层:
parent(顶级 )pom
-- api(公共API、DTO等)jar
-- foundation(公共基设)jar
-- modules(前端consumer)pom
-- www(官网)jar
-- admin(后台)jar
-- ......
-- service(provider,本应该拆分,我这里只写了一个) pom
-- user(用户中心)jar
-- order(订单中心)jar
-- ......
所用技术: springboot、dubbo、zookeeper、mybatis、redis、RabbitMQ、druid、swagger等
效果截图:
自动生成的swagger接口文档,可直接测试:
使用druid的SQL监控,记录慢SQL:
dubbo admin:
RabbitMQ admin:
项目截图:
部分代码:
消费者(暴露给前端的controller)
package com.ysk.admin.controller;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.ysk.api.model.User;
import com.ysk.api.service.UserService;
@RestController
@RequestMapping("/")
public class TestController {
@Reference(version = "1.0.0")
private UserService testService;
@GetMapping("hello")
public String hello() {
return testService.sayHello("Hello springboot and dubbo!");
}
@GetMapping("user")
public User user() {
return testService.findUser();
}
@GetMapping("list")
public List list(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int pageSize) {
return testService.getUser(page, pageSize);
}
@RequestMapping(value = "add", method = RequestMethod.POST)
public List add(@RequestBody User user) {
System.out.println(user.toString());
return null;
}
// 从redis获取某个用户
@RequestMapping(value = "getuserfromredis", method = RequestMethod.GET)
public User getRedis(@RequestParam String key) {
return testService.getUserForRedis(key);
}
}
package com.ysk.admin;
import org.apache.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource({ "classpath:config/spring-dubbo.xml" })
public class App {
private static Logger logger = Logger.getLogger(App.class);
public static void main(String[] args) {
SpringApplication.run(App.class, args);
logger.info("SpringBoot Start Success");
}
}
提供者(具体的实现与逻辑)
package com.ysk.service.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageHelper;
import com.ysk.api.model.User;
import com.ysk.api.service.UserService;
import com.ysk.resource.UserMapper;
import com.ysk.service.RedisService;
@Service(version = "1.0.0", interfaceClass = UserService.class)
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RedisService redisService;
@Override
public String sayHello(String str) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
return dateFormat.format(new Date()) + ": " + str;
}
@Override
public User findUser() {
User user = new User();
user.setId(1001);
user.setName("张三");
user.setAge(20);
user.setAddress("上海徐汇");
return user;
}
@Override
public List getUser(int page, int pageSize) {
PageHelper.startPage(page, pageSize);
return userMapper.getUsers();
}
@Override
public User getUserForRedis(String key) {
User user = new User();
user.setId(1008);
user.setName("刘德华");
user.setAge(60);
user.setAddress("中国香港");
redisService.set(user.getId() + "", user);
return (User) redisService.get(key);
}
}
package com.ysk.config;
import java.util.Properties;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.TransactionInterceptor;
@Configuration
public class TransactionConfiguration {
@Bean(name = "transactionInterceptor")
public TransactionInterceptor transactionInterceptor(PlatformTransactionManager platformTransactionManager) {
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
// 事务管理器
transactionInterceptor.setTransactionManager(platformTransactionManager);
Properties transactionAttributes = new Properties();
// 新增
transactionAttributes.setProperty("insert*", "PROPAGATION_REQUIRED,-Throwable");
// 修改
transactionAttributes.setProperty("update*", "PROPAGATION_REQUIRED,-Throwable");
// 删除
transactionAttributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Throwable");
// 查询
transactionAttributes.setProperty("select*", "PROPAGATION_REQUIRED,-Throwable, readOnly");
transactionInterceptor.setTransactionAttributes(transactionAttributes);
return transactionInterceptor;
}
// 代理到ServiceImpl的Bean
@Bean
public BeanNameAutoProxyCreator transactionAutoProxy() {
BeanNameAutoProxyCreator transactionAutoProxy = new BeanNameAutoProxyCreator();
transactionAutoProxy.setProxyTargetClass(true);
transactionAutoProxy.setBeanNames("*ServiceImpl");
transactionAutoProxy.setInterceptorNames("transactionInterceptor");
return transactionAutoProxy;
}
}
package com.ysk.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfiguration {
// 声明队列
@Bean
public Queue queue1() {
return new Queue("hello.queue1", true); // true表示持久化该队列
}
@Bean
public Queue queue2() {
return new Queue("hello.queue2", true);
}
// 声明交互器
@Bean
TopicExchange topicExchange() {
return new TopicExchange("topicExchange");
}
// 绑定
@Bean
public Binding binding1() {
return BindingBuilder.bind(queue1()).to(topicExchange()).with("key.1");
}
@Bean
public Binding binding2() {
return BindingBuilder.bind(queue2()).to(topicExchange()).with("key.#");
}
}
package com.ysk.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
@EnableCaching
public class RedisConfiguration extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisTemplate,?> redisTemplate) {
CacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
spring.datasource.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
#连接池的配置信息
spring.datasource.initial-size=5
spring.datasource.min-idle=5
spring.datasource.max-idle=8
spring.datasource.max-active=20
spring.datasource.max-wait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat,wall,log4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=200
server.port=8082
server.context-path=/
logging.level.com.ysk.resource=debug
# MyBatis 配置
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml
mybatis.type-aliases-package=com.ysk.api.model
#druid 配置
druid.username=admin
druid.password=admin
druid.allow=127.0.0.1
druid.reset.enable=true
#redis
spring.redis.hostName=127.0.0.1
spring.redis.port=6379
spring.redis.pool.maxActive=8
spring.redis.pool.maxWait=-1
spring.redis.pool.maxIdle=8
spring.redis.pool.minIdle=0
spring.redis.timeout=0
#rabbitMQ
spring.rabbitmq.host=10.99.2.10
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin123
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.template.mandatory=true
# 最小消息监听线程数
spring.rabbitmq.listener.concurrency=2
spring.rabbitmq.listener.max-concurrency=2