项目笔记:EGO商城

项目系统架构图

在这里插入图片描述

项目功能模块划分

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.后台系统登录

  1. 使用PageController控制页面访问
  2. 使用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.新增商品

  1. 商品图片文件上传
    使用kindeditor完成图片文件上传至FastDFS文件服务器
    根据kindeditor要求返回的数据格式,更推荐使用Map而非再创建一个自定义类

  2. 商品类目查询并树状展示(对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;
    }
    
  3. 新增商品和商品描述(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.商品修改

  1. 修改页面的显示

  2. 根据商品ID查询商品描述
    服务消费者返回EgoResult,其中date属性为TbItemDesc
    TbItemDesc TbItemDescDubboService.selectById(long id)
    EgoResult TbItemDescService.showDesc(long id);

  3. 更新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

配置文件:

  1. fdfs_client.conf - 配置用于连接FastDFS
  2. spring-commons.yml - 配置了FastDFS的Nginx Host

类文件:

  1. EgoResult.java - 用于封装一般返回结果
  2. EasyUIDatagrid.java - 用于封装分页数据返回结果
  3. FastDFSClient.java - 用于进行FastDFS操作的工具类
  4. DaoException.java - 用于DAO层异常处理,进行事务回滚的自定义异常类
  5. EasyUITree.java - 用于封装满足EasyUI Tree组件的返回结果
  6. 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

配置文件:

  1. 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

接口文件:

  1. ManagerDubboService - 用于规范manager表操作
  2. TbItemDubboService - 用于规范item表操作
  3. 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

配置文件:

  1. application.yml - 用于配置Dubbo服务的基本信息、加载依赖中的其他配置文件信息

启动类文件:

  1. ProviderApp.java - 用于启动Dubbo服务提供方

实现类文件:

  1. ManagerDubboServiceImpl.java
  2. TbItemDubboServiceImpl.java
  3. 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

配置文件:

  1. application.yml - 用于配置Dubbo服务基本信息、web访问端口、视图解析器

启动类文件:

  1. ManagerApp.java - 用于启动Dubbo服务消费方应用

配置类文件:

  1. SecurityConfig.java - 用于配置Spring Security的自定义认证逻辑

控制类文件:

  1. PageController.java - 用于页面控制
  2. ImgController.java - 用于商品图片控制

接口类文件:

  1. TbItemService.java - 用于规范item表格操作
  2. ImgService.java - 用于规范商品图片文件上传操作
  3. TbItemCatService.java

实现类文件:

  1. LoginServiceImpl.java - 用于实现自定义登录认证逻辑
  2. TbItemServiceImpl.java - 用于实现item表格操作
  3. 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){...}
}

问题反思

1.关于Exception与RuntimeException的事务差异

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值