- 项目系统架构图
- 项目功能模块划分
- 1.ego_parent - 父模块
- 2.ego_pojo - 实体类模块
- 4.ego_mapper - 数据库访问模块
- 3.ego_api - 服务接口模块
- 5.ego_provider - 服务接口实现模块
- 6.ego_commons -公共资源模块(工具类、数据传输类)
- 7.ego_manage - 后台管理系统模块
- 8.ego_portal - 门户模块
- 9.ego_search - 商品搜索模块
- 10.ego_item - 商品模块
- 11.ego_cart - 购物车模块
- 12.ego_passport - 单点登录模块
- 13.ego_trade - 订单模块
- 14.ego_redis - Redis操作模块
- 15.ego_rebbitmq_send - RabbitMQ消息发送模块
- 16.ego_rabbitmq_receive - RabbitMQ消息监听队列模块
- 项目环境搭建
- 功能服务
- 工程创建
- 问题反思
项目系统架构图
项目功能模块划分
1.ego_parent - 父模块
提供统一的依赖管理
2.ego_pojo - 实体类模块
使用MyBatis Generator生成POJO
4.ego_mapper - 数据库访问模块
使用MyBatis Generator生成MAPPER
3.ego_api - 服务接口模块
5.ego_provider - 服务接口实现模块
6.ego_commons -公共资源模块(工具类、数据传输类)
7.ego_manage - 后台管理系统模块
8.ego_portal - 门户模块
9.ego_search - 商品搜索模块
10.ego_item - 商品模块
11.ego_cart - 购物车模块
12.ego_passport - 单点登录模块
13.ego_trade - 订单模块
14.ego_redis - Redis操作模块
15.ego_rebbitmq_send - RabbitMQ消息发送模块
16.ego_rabbitmq_receive - RabbitMQ消息监听队列模块
项目环境搭建
1.IntelliJ IDEA安装
配置号jdk环境及maven环境
2.注册中心ZooKeeper部署
VMware中安装Server版CentOS,在CentOS中安装Zookeeper
IP:192.168.54.100
3.文件服务器FastDFS部署
VMware中安装Server版CentOS,在CentOS中安装FastDFS
安装配置Nginx
IP:192.168.54.101
功能服务
1.后台系统登录
- 使用PageController控制页面访问
- 使用spring security实现登录服务(对manager表的查询)
2.查询商品
查询item表的所有数据
3.商品上架、下架、删除
根据商品主键对item表进行修改
商品批量处理时,不建议dubbo consumer多次调用dubbo provider,而是建议直接在dubbo provider中进行批量处理
dubbo provider中如果操作失败,建议抛出自定义DAO EXCEPTION进行回滚,该异常类使用RuntimeException即可,但也可以使用CheckedExcption来强制进行处理(但此时如果要实现事务回滚,需要在@Transactional使用rollbackFor=Exception.class参数
//检查时异常类
public class DaoException extends Exception{...}
//事务回滚
@Override
@Transactional(rollbackFor=Exception.class)
...
//运行时异常类
public class DaoException extends RuntimeException{...}
//事务回滚
@Override
@Transactional
...
4.新增商品
-
商品图片文件上传
使用kindeditor完成图片文件上传至FastDFS文件服务器
根据kindeditor要求返回的数据格式,更推荐使用Map而非再创建一个自定义类 -
商品类目查询并树状展示(对item_cat表的查询)
树状节点是展开还是关闭,是根据isParent属性判断@Override public List<EasyUITree> showItemCatTree(long pid){ //构建封装对象 List<EasyUITree> listTree=new ArrayList<>(); //查询商品条目 List<TbItemCat> list=tbItemCatDubboService.selectByPid(pid); //封装 for(TbItemCat cat:list){ //构建封装对象 EasyUITree tree=new EasyUITree(); //封装 tree.setId(cat.getId()); tree.setText(cat.getText()); //节点是展开还是关闭 tree.setState(cat.getIsParent()?"closed":"open"); listTree.add(tree); } return listTree; }
-
新增商品和商品描述(item表和item_desc表的新增)
两表新增都直接在TbItemDubboService中进行,不用拆分到TbItemDescDubboService中了@Override @Transactional public int insert(TbItem tbItem,TbItemDesc tbItemDesc) throws DaoException{ int result=tbItemMapper.insert(tbItem); if(result == 1){ //新增商品成功后再新增商品描述 result +=tbItemDescMapper.insert(tbItemDesc); //商品描述新增成功后再返回1 if(result == 2){ return 1; } } //否则抛出异常,直接回滚 throw new DaoException("商品新增失败"); }
还有一些属性都在服务消费方的实现类中进行处理
@Override public EgoResult add(TbItem tbItem,String desc){ //构建参数 Date date=new Date(); long id=IDUtil.getItemId(); TbItemDesc tbItemDesc=new TbItemDesc(); //封装 tbItem.setCreated(date); tbItem.setUpdated(date); tbItem.setId(id); tbItem.setStatus((byte)1); tbItemDesc.setItemId(id); tbItemDesc.setItemDesc(desc); tbItemDesc.setCreated(date); tbItemDesc.setUpdated(date); //调用服务并进行事务处理 try{ int result=tbItemDubboService.insert(tbItem,tbItemDesc); if(1 == result){ return EgoResult.ok(); } }catch(DaoException e){ e.printStackTrace(); } return EgoResult.error("商品新增失败"); }
5.商品修改
-
修改页面的显示
-
根据商品ID查询商品描述
服务消费者返回EgoResult,其中date属性为TbItemDesc
TbItemDesc TbItemDescDubboService.selectById(long id)
EgoResult TbItemDescService.showDesc(long id); -
更新item表和item_desc表
6.
工程创建
1.ego_parent
// pom.xml
<!--声明所有spring boot相关版本-->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<!--版本管理-->
<properties></properties>
<!--依赖管理-->
<denpendencyManagement>
<!--spring session分布式事务-->
<artifactId>spring-session-data-redis</artifactId>
<!--spring boot启动器-->
<artifactId>spring-boot-starter</artifactId>
<!--spring mvc-->
<artifactId>spring-boot-starter-web</artifactId>
<!--spring security-->
<artifactId>spring-boot-starter-security</artifactId>
<!--dubbo-->
<artifactId>dubbo-spring-boot-starter</artifactId>
<artifactId>curator-recipes</artifactId>
<artifactId>curator-framework</artifactId>
<!--mybatis-->
<artifactId>mybatis-spring-boot-starter</artifactId>
<artifactId>mysql-connector-java</artifactId>
<!--jsp解析器-->
<artifactId>jstl</artifactId>
<artifactId>tomcat-embed-jasper</artifactId><scope>provided</scope>
<!--druid-->
<artifactId>druid-spring-boot-starter</artifactId>
<!--pagehelper-->
<artifactId>pagehelper-spring-boot-starter</artifactId>
<artifactId>pagehelper</artifactId>
<!--fastdfs-->
<artifactId>fastdfs-client</artifactId>
<artifactId>commons-lang3</artifactId>
<!--solr-->
<artifactId>spring-boot-statert-data-solr</artifactId>
<!--redis-->
<artifactId>spring-boot-starter-data-redis</artifactId>
<!--rabbitmq-->
<artifactId>spring-boot-starter-amqp</artifactId>
<!--httpclient-->
<artifactId>httpclient</artifactId>
<!--jackson-->
<artifactId>jackson-databind</artifactId>
<!--servlet-->
<artifactId>javax-servlet-api</artifactId><scope>provided</scope>
<artifactId>spring-web</artifactId>
<!--java mail-->
<artifactId>spring-boot-starter-mail</artifactId>
<!--视图模板技术-->
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependencyManagement>
ego_commons
配置文件:
- fdfs_client.conf - 配置用于连接FastDFS
- spring-commons.yml - 配置了FastDFS的Nginx Host
类文件:
- EgoResult.java - 用于封装一般返回结果
- EasyUIDatagrid.java - 用于封装分页数据返回结果
- FastDFSClient.java - 用于进行FastDFS操作的工具类
- DaoException.java - 用于DAO层异常处理,进行事务回滚的自定义异常类
- EasyUITree.java - 用于封装满足EasyUI Tree组件的返回结果
- IDUtil.java - 用于生成主键ID
public class EgoResult{
private int status;
private Object data;
private String msg;
public static EgoResult ok(){
return new EgoResult(200,"ok");
}
public static EgoResult ok(String msg){
return new EgoResult(200,msg);
}
public static EgoResult ok(Object data){
return new EgoResult(200,data,"ok");
}
...
}
public class EasyUIDatagrid{
//总数据量
private long total;
//每页数据集合
private List<Object> rows;
}
// 用于DAO层事务回滚
public class DaoException extends RuntimeException{
//自定义有参DAO层异常
public DaoException(String message){
super(message);
}
}
public class EasyUITree{
//节点ID
private Long id;
//节点标题
private String text;
//节点状态
private String state;
}
2.ego_pojo
3.ego_mapper
配置文件:
- application-mapper.yml - 配置数据源及MyBatis的mapper路径信息
//application-mapper.yml
# 配置数据源
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ego?useSSL=false&characterEncoding=utf-8
username: root
password: root
# 配置连接池
druid:
initial-size: 5
min-idle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 配置PSCache
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters
filters: stat,wall,slf4j
# 配置mergeSql功能 - 慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=500
# 配置DruidStatFilter
web-stat-filter:
enabled: true
url-pattern: "/*"
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
# 配置DruidStatViewServlet
stat-view-servlet:
url-pattern: "/druid/*"
# 配置IP白名单(空则表示允许所有访问)
allow: 127.0.0.1,192.168.54.1
# 配置IP黑名单(同时存在,deny优于allow)
deny: 192.168.54.2
# 禁用页面中的"Reset All"
reset-enable: false
# 配置登录信息
login-username: admin
login-password: 123
# 配置mybatis
mybatis:
mapper-locations: classpath:mybatis/*.xml
3.ego_api
接口文件:
- ManagerDubboService - 用于规范manager表操作
- TbItemDubboService - 用于规范item表操作
- TbItemCatDubboService - 用于规范item_cat表操作
public interface ManagerDubboService{
//根据用户名查询用户信息
Manager selectManagerByUsername(String username);
}
public interface TbItemDubboService{
//分页查询所有商品
List<TbItem> selectByPage(int pageSize,int pageNumber);
//查询商品总数量
long selectCount();
//根据商品ID批量更新商品状态
int updateStatusByIds(long[] ids,int status) throws DaoException;
//新增商品
int insert(TbItem tbItem,TbItemDesc tbItemDesc);
}
public interface TbItemCatDubboService{
//根据父ID查询子类目
List<TbItemCat> selectByPid(long pid);
}
3.ego_provider
配置文件:
- application.yml - 用于配置Dubbo服务的基本信息、加载依赖中的其他配置文件信息
启动类文件:
- ProviderApp.java - 用于启动Dubbo服务提供方
实现类文件:
- ManagerDubboServiceImpl.java
- TbItemDubboServiceImpl.java
- TbItemCatDubboServiceImpl.java
//application.yml
# 配置当前项目所依赖的jar项目中的appliction-xx.yml文件(通过xx名称进行加载)
# 加载ego_mapper模块中src/main/resources/mybatis/application-mapper.yml
spring:
profiles:
active: mapper
# 配置dubbo服务
dubbo:
# 配置服务名称
application:
name: ego-provider
# 配置注册中心地址
registry:
address: zookeeper://192.168.54.100:2181
// ProviderApp.java
@SpringBootApplication
@EnableDubbo
@MapperScan("com.ego.mapper")
public class ProviderApp{...}
ego_manage
配置文件:
- application.yml - 用于配置Dubbo服务基本信息、web访问端口、视图解析器
启动类文件:
- ManagerApp.java - 用于启动Dubbo服务消费方应用
配置类文件:
- SecurityConfig.java - 用于配置Spring Security的自定义认证逻辑
控制类文件:
- PageController.java - 用于页面控制
- ImgController.java - 用于商品图片控制
接口类文件:
- TbItemService.java - 用于规范item表格操作
- ImgService.java - 用于规范商品图片文件上传操作
- TbItemCatService.java
实现类文件:
- LoginServiceImpl.java - 用于实现自定义登录认证逻辑
- TbItemServiceImpl.java - 用于实现item表格操作
- ImgServiceImpl.java - 用于实现商品图片文件上传
# 配置dubbo
dubbo:
application:
name: ego-manage
registry:
address: zookeeper://192.168.54.100:2181
# 配置访问端口
server:
port: 80
# 配置视图解析器
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
# 配置访问其他配置文件
profiles:
active: commons
@SpringBootApplication
//consumer中@EnableDubbo可省略
@EnableDubbo
public class ManageApp{...}
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
//配置密码编码器
@Bean
protected PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//自定义登录认证逻辑
@Override
protected void configure(HttpSecurity http) throws Exception{
//配置登录
http.formLogin()
//登录页面
.loginPage("/")
//登录请求路径
.loginProcessingUrl("/login")
//登录成功后转发路径
.successForwardUrl("/loginSuccess");
//配置拦截
http.authorizeRequests()
//放行路径
.antMatchers("/","/css/**","/js/**","").permitAll()
//拦截路径
.anyRequest().authenticated();
//关闭csrf防护
http.csrf().disable();
}
}
@Service
public class LoginServiceImpl implements UserDetailService{
@Reference
private ManagerDubboService managerDubboService;
//自定义用户登录验证
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
Manager manager=managerDubboService.selectManagerByUserName(username);
if(null == manager){
throw new UsernameNotFoundException("用户不存在");
}
return new User(username,manager.getPassword(),AuthorityUtils.commaSeparaterdStringToAuthorityList(""));
}
}
@Controller
public class PageController{
//登录页面显示
@RequestMapping("/")
public String login(){...}
//登录成功跳转
@RequestMapping("loginSuccess")
@ResponseBody
public EgoResult loginSuccess(){}
//显示主页
@RequestMapping("/main")
public String showIndex(){...}
//显示对应页面
@RequestMapping("{/page}")
public String showPage(@PathVariable String page){...}
}
public interface TbItemService{
//分页显示所有商品
EasyUIDatagrid showItem(int page,int rows);
//根据ID修改商品状态 1-上架 2-下架 3-删除
EgoResult updateStatusByIds(long[] ids,int status);
//新增商品
EgoResult add(TbItem tbItem,String desc);
}
@Controller
public class TbItemController[
//分页查询所有商品
@RequestMapping("/item/list")
@ResponseBody
public EasyUIDatagrid showItem(int page,int rows){...}
//删除商品
@RequestMapping("/rest/item/delete")
@ResponseBody
public EgoResult deleteItem(long[] ids){...}
//商品上架
@RequestMapping("/rest/item/reshelf")
@ResponseBody
public EgoResult reshelfItem(long[] ids){...}
//商品下架
@RequestMapping("/rest/item/instock")
@ResponseBody
public EgoResult intstockItem(long[] ids){...}
//商品新增
@RequestMapping("/rest/item/save")
@ResponseBody
public EgoResult add(TbItem tbItem,String desc){...}
}
public interface ImgService{
//商品图片文件上传
Map<String,Object> uploadImg(MultipartFile file);
}
@Controller
public class ImgController{
//商品图片上传
@RequestMapping("/img/upload")
@ResponseBody
public Map<String,Object> imgUpload(MultipartFile uploadFile);
}
public interface TbItemCatService{
//显示商品类目树状菜单
List<EasyUITree> showItemCatTree(long pid);
}
@Controller
public class TbItemCatController{
//显示商品类目树状菜单
@RequestMapping("/item/cat/list")
@ResponseBody
public List<EasyUITree> showItemCatTree(@RequestParam(defaultValue="0") long pid){...}
}