1.项目预计
序列1-地址:https://github.com/Jonekaka/javaweb-qingcheng-1-76/tree/master/qingchengcode/qingchengcode
1.1小项目特点
对于一些小项目ssm就够了,但是对于高并发的大项目
需要更多新技术的融合与赋能
1.2大项目特点
技术新,技术范围广-技术
分布式、集群、高并发、负载均衡、高可用-设备压力分担
海量数据-数据
业务复杂-业务
系统安全-安全
将多个小设备虚拟为一个超算
1.3 主要电商模式
B2B ( Business to Business)是指进行电子商务交易的供需双方都是商家(或企
业、公司),她(他)们使用了互联网的技术或各种商务网络平台,完成商务交易的
过程。电子商务是现代 B2B marketing的一种具体主要的表现形式。
案例:阿里巴巴、慧聪网
C2C即 Customer(Consumer) to Customer(Consumer),意思就是消费者个
人间的电子商务行为。比如一个消费者有一台电脑,通过网络进行交易,把它出售给
另外一个消费者,此种交易类型就称为C2C电子商务。
案例:淘宝、易趣、瓜子二手车
B2C是Business-to-Customer的缩写,而其中文简称为“商对客”。“商对客”是电子商
务的一种模式,也就是通常说的直接面向消费者销售产品和服务商业零售模式。这种
形式的电子商务一般以网络零售业为主,主要借助于互联网开展在线销售活动。B2C
即企业通过互联网为消费者提供一个新型的购物环境——网上商店,消费者通过网络
在网上购物、网上支付等消费行为。
注:本项目采用B2C模式
案例:唯品会、乐蜂网B2B2C是一种电子商务类型的网络购物商业模式,B是BUSINESS的简称,C是
CUSTOMER的简称,第一个B指的是商品或服务的供应商,第二个B指的是从事电子
商务的企业,C则是表示消费者。
案例:京东商城、天猫商城
C2B(Consumer to Business,即消费者到企业),是互联网经济时代新的商业模
式。这一模式改变了原有生产者(企业和机构)和消费者的关系,是一种消费者贡献
价值(Create Value), 企业和机构消费价值(Consume Value)。
C2B模式和我们熟知的供需模式(DSM, Demand SupplyModel)恰恰相反,真正的
C2B 应该先有消费者需求产生而后有企业生产,即先有消费者提出需求,后有生产
企业按需求组织生产。通常情况为消费者根据自身需求定制产品和价格,或主动参与
产品设计、生产和定价,产品、价格等彰显消费者的个性化需求,生产企业进行定制
化生产。
案例:海尔商城、 尚品宅配
O2O即Online To Offline(在线离线/线上到线下),是指将线下的商务机会与互联
网结合,让互联网成为线下交易的平台,这个概念最早来源于美国。O2O的概念非
常广泛,既可涉及到线上,又可涉及到线下,可以通称为O2O。主流商业管理课程均
对O2O这种新型的商业模式有所介绍及关注。
案例:美团、饿了吗
F2C指的是Factory to customer,即从厂商到消费者的电子商务模式。
2. 青橙-需求分析与系统设计
2.1 需求分析
《青橙》是一个全品类B2C电商平台(单品类就是只卖一类,比如衣服,化妆品),包含网站前台和管理后台两大部分。网站前台
包含主站频道(首页、搜索、购物车及支付)、用户中心、秒杀、优惠券等频道。管理
后台包含商品、订单、库存、用户、运营、统计、财务、设置等功能
后台
前台
等等,商品详情页,登录页,评论页
2.2 系统设计
2.2.1 数据库分库设计
(1)商品库 qingcheng_goods
(2)订单库 qingcheng_order
(3)基础设置库 qingcheng_config
(4)运营库 qingcheng_business
(5)用户库 qingcheng_user
(6)系统库qingcheng_system
(7)支付库 qingcheng_pay
(8)短信库 qingcheng_sms
2.2.2 技术选型
主框架技术:SSM(通用mapper,比mybatis使用更加简单)+Dubbo(分布式框架)
前端技术: 网站后台 Vue.js+ElementUI(ui库) 网站前台采用Vue.js 和模板技术 thymeleaf
消息中间件技术: RabbitMQ
搜索中间件技术: elasticsearch
缓存中间件技术: redis
报表插件: echars
安全框架:SpringSecurity
单点登录中间件 :CAS
2.2.3 系统架构图
3. 通用mapper
3.1 通用mapper简介
对mybatis进行了进一步封装,解决mybatis存在的问题
通用 Mapper 是一个可以实现任意 MyBatis 通用方法的框架,项目提供了常规的增
删改查操作以及Example相关的单表操作。为什么要用通用mapper?我们这里列举一下
原生Mybatis的痛点:
1、mapper.xml文件里有大量的sql,当数据库表字段变动,配置文件就要修改
2、需要自己实现sql分页,select * from table where . . . limit 1,3
自己手写分页,除了传参page、pageSize,还需要返回条目总数count。
3、数据库可移植性差:如果项目更换数据库,比如oracle–>mysql,mapper.xml中的
sql要重新写,因为Oracle的PLSQL 和mysql 支持的函数是不同的。
4、生成的代码量过大。
5、批量操作,批量插入,批量更新,需要自写。
而这些,通过通用mapper就可以很轻松的解决了。
3.2 通用mapper快速入门
在线官方文档:https://gitee.com/free/Mapper/wikis/Home
3.2.1 通用mapper与Spring集成
官方的文档中介绍了通用mapper的三种使用方式 ,纯java使用方式、与Spring集成方
式、与SpringBoot集成方式。这里给大家介绍的是与Spring集成方式。
如果对语句抽象化,自动生成,自然能够避免表不同,数据库语法不同而带来的修改问题
同时也可以实现扩展功能,比如自动分页
也可以批量完成
实现数据库接口crud调用mapper提供的功能接口即可
(1)引入依赖
正常情况下,Spring 和 MyBatis 的集成环境中,应该已经存在下面的依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>版本号</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis‐spring</artifactId>
<version>版本号</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring‐context</artifactId>
<version>版本号</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring‐tx</artifactId>
<version>版本号</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring‐jdbc</artifactId>
<version>版本号</version>
</dependency>
集成通用 Mapper 在上面的基础上添加下面的依赖:
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>最新版本</version>
</dependency>
(2)与spring集成
和通用 Mapper 以前版本一样,可以直接使用 tk.mybatis 提供
的 tk.mybatis.spring.mapper.MapperScannerConfigurer 进行配置,这个配置和
MyBatis 官方提供的 org.mybatis.spring.mapper.MapperScannerConfigurer 区别只是
第一层的包名, tk 和 org 。所以使用这种方式时,如果你项目已经使用 org. 进行了
配置,只需要改成 tk. 即可。
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="扫描包名"/>
</bean>
项目中采用的是这种xml的配置方式,通用mapper还提供了注解方式的配置,
3.2.2 实体类映射
实体类映射类似下列形式
@Table(name="tb_brand")
public class Brand implements Serializable{
@Id
private Integer id;
private String name;
//getter and setter ....
}
@Table是指定实体类对应的数据库表 @Id指的是主键映射。经过上面简单的配置后,相
当于就有了 MyBatis 中的关系映射了
3.2.3 创建Mapper接口
public interface BrandMapper extends Mapper<Brand> {
}
这里继承了 tk.mybatis.mapper.common.Mapper 接口,在接口上指定了泛型类
型 Brand 。当你继承了 Mapper 接口后,此时就已经有了针对 Brand 的大量方法,方
法如下:
等等》》》
这些方法中和 MBG 生成的大部分方法都一致,还有一部分 MBG 之外的常用方法。
基础接口select
List select(T record)
根据T对象中的属性名称查询,类似于select * from table where t.name=#{name} and
t.password = #{password}
T selectOne(T record)
根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
T selectByPrimaryKey(Object key)
根据主键查询 说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条
件使用等号
int selectCount(T record);
说明:根据实体中的属性查询总数,查询条件使用等号基础接口insert
int insert(T record);
说明:保存一个实体,null的属性也会保存,不会使用数据库默认值
int insertSelective(T record);
说明:保存一个实体,null的属性不会保存,会使用数据库默认值
基础接口Update
int updateByPrimaryKey(T record);
说明:根据主键更新实体全部字段,null值会被更新
int updateByPrimaryKeySelective(T record);
说明:根据主键更新属性不为null的值
基础接口delete
int delete(T record);
说明:根据实体属性作为条件进行删除,查询条件使用等号
int deleteByPrimaryKey(Object key);
说明:根据主键字段进行删除,方法参数必须包含完整的主键属性
- 青橙-工程搭建
4.1 准备工作
先进行环境准备
(1)配置maven本地仓库
(2)创建数据库表
(3)注册中心zookeeper
4.2 模块依赖关系图
我们的工程有三种模块:(1)公共模块(解决模块的重复问题,这里主要是服务层与web层的重复问题,以及模块重复带来的复杂性-面向对象的思想) (2)服务层模块 (3)web层模块。
公共模块主要由公共配置和公共类构成。模块依赖关系入下图:
4.3 工程搭建
4.3.1 父工程与公共模块
(1)创建父工程qingcheng_parent pom.xml
父工程没有代码,删掉src文件夹
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>qingcheng_common</module>
<module>qingcheng_common_service</module>
<module>qingcheng_common_web</module>
<module>qingcheng_pojo</module>
<module>qingcheng_interface</module>
<module>qingcheng_service_goods</module>
<module>qingcheng_web_manager</module>
</modules>
<packaging>pom</packaging>
<!-- 集中定义依赖版本号 -->
<properties>
<junit.version>4.12</junit.version>
<spring.version>5.0.5.RELEASE</spring.version>
<pagehelper.version>4.1.4</pagehelper.version>
<servlet-api.version>2.5</servlet-api.version>
<dubbo.version>2.6.0</dubbo.version>
<zookeeper.version>3.4.7</zookeeper.version>
<zkclient.version>0.1</zkclient.version>
<mybatis.version>3.4.5</mybatis.version>
<mybatis.spring.version>1.3.1</mybatis.spring.version>
<mybatis.paginator.version>1.2.15</mybatis.paginator.version>
<mysql.version>5.1.32</mysql.version>
<druid.version>1.0.9</druid.version>
<commons-fileupload.version>1.3.1</commons-fileupload.version>
<spring.security.version>5.0.5.RELEASE</spring.security.version>
<jackson.version>2.9.4</jackson.version>
</properties>
<!-- 依赖管理标签 必须加 -->
<dependencyManagement>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${
spring.version}</version>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${
dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${
zookeeper.version}</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>${
zkclient.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${
pagehelper.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${
mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${
mybatis.spring.version}</version>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>${
mybatis.paginator.version}</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${
mysql.version}</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${
druid.version}</version>
</dependency>
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${
commons-fileupload.version}</version>
</dependency>
<!-- 安全框架 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${
spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${
spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${
spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
<version>${
spring.version}</version>
</dependency>
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${
jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${
jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${
jackson.version}</version>
</dependency>
<!--通用Mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.1.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${
servlet-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!--为了使用jdk1.8新特性,引入。-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
上面为父
(2)创建公共模块qingcheng_common,pom.xm
搭建公共模块,从最顶层开始搭建
提供基础参数
resources下创建applicationContext-common.xml
<!--用来加载所有文件名末尾属性为properties的文件-->
<context:property-placeholder location="classpath*:*.properties" />
resources下创建zk.properties
zk.properties
#配置zk连接地址地址
zk.address=127.0.0.1:2181
resources下创建log4j.properties
配置日志参数
(3)创建qingcheng_common_service ,pom.xml
搭建服务公共模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qingcheng_parent</artifactId>
<groupId>com.qingcheng</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qingcheng_common_service</artifactId>
<!--引入common依赖,传递依赖,-->
<dependencies>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!--通用Mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
</dependencies>
</project>
resources下创建applicationContext-dao.xml,mybatis的
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--数据源的一些配置-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="plugins">
<!--mybatis的插件,分页-->
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
dialect=mysql
</value>
</property>
</bean>
</array>
</property>
</bean>
<!--包扫描-->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.qingcheng.dao" />
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--
开启事务控制的注解支持
注意:此处必须加入proxy-target-class="true",
需要进行事务控制,会由Spring框架产生代理对象,Dubbo需要将Service发布为服务,要求必须使用cglib创建代理对象。
-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
</beans>
resources下创建applicationContext-dubbo.xml,dubbo的
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定暴露服务的端口,如果不指定默认为20880-->
<dubbo:protocol name="dubbo" port="${dubbo.port}"/>
<dubbo:application name="${dubbo.application}" />
<!--zk地址为common而来-->
<dubbo:registry protocol="zookeeper" address="${zk.address}" />
<dubbo:annotation package="com.qingcheng.service" />
<!--<context:annotation-config/>-->
<dubbo:provider timeout="10000" threadpool="fixed" threads="100" accepts="1000"/>
</beans>
redis的
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/beans/spring-cache.xsd">
<!-- redis 相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!--spring data redis的配置,使用中会用到配置文件,已经添加-->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
</beans>
(4)创建qingcheng_common_web模块,pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qingcheng_parent</artifactId>
<groupId>com.qingcheng</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!--传递依赖-->
<artifactId>qingcheng_common_web</artifactId>
<dependencies>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--文件上传相关依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!--spring安全依赖-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<!--阿里提供的存储对象依赖-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
</dependencies>
</project>
resources下创建applicationContext-json.xml
<mvc:annotation‐driven>
<mvc:message‐converters register‐defaults="true">
<bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
<property name="features">
<list>
<value>WriteMapNullValue</value>
<value>WriteDateUseDateFormat</value>
</list>
</property>
</bean>
</mvc:message‐converters>
</mvc:annotation‐driven>
resources下创建applicationContext-dubbo.xml
<!-- 引用dubbo 服务,为工程起名字 -->
<dubbo:application name="${dubbo.application}" />
<!--对zk地址配置-->
<dubbo:registry protocol="zookeeper" address="${zk.address}"/>
<!--扫描所有控制器的类-->
<dubbo:annotation package="com.qingcheng.controller" />
下面两个模块也会被其他模块所引用,也可以归类为公共模块
(5)创建实体层模块qingcheng_pojo,pom.xml
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence‐api</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
(6)创建服务接口层模块 qingcheng_interface ,pom.xml
<!--jpa注解-->
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_pojo</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
4.3.2 服务层模块(商品)
其中一个为例子,其他一样
商品服务
(1)创建qingcheng_service_goods模块,pom.xml
<dependencies>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_interface</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_common_service</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
</dependencies>
<!--指定各个服务的端口,创建各自的服务器。从9001开始-->
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7‐maven‐plugin</artifactId>
<configuration>
<!‐‐ 指定端口 ‐‐>
<port>9001</port>
<!‐‐ 请求路径 ‐‐>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
(2)创建webapp/WEB-INF/web.xml
<!DOCTYPE web‐app PUBLIC
"‐//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web‐app_2_3.dtd" >
<web‐app>
<display‐name>Archetype Created Web Application</display‐name>
<!‐‐ 加载spring容器 ‐‐>
<context‐param>
<param‐name>contextConfigLocation</param‐name>
<param‐value>classpath*:applicationContext*.xml</param‐value>
</context‐param>
<listener>
<listener‐
class>org.springframework.web.context.ContextLoaderListener</listener‐
class>
</listener>
</web‐app>
(3)resources下创建dubbo.properties
配置功能区的端口与名字
dubbo.port=20881
dubbo.application=goods
(4)resources下创建db.properties
配置数据库连接信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/qingcheng_goods?
characterEncoding=utf‐8
jdbc.username=root
jdbc.password=123456
4.3.3 web层(管理后台)
(1)创建qingcheng_web_manager模块,pom.xml
<dependencies>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_interface</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.qingcheng</groupId>
<artifactId>qingcheng_common_web</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7‐maven‐plugin</artifactId>
<configuration>
<!‐‐ 指定端口 ‐‐>
<port>9101</port>
<!‐‐ 请求路径 ‐‐>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
(2)创建webapp/WEB-INF/web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--安全框架的过滤器,暂时不用-->
<!--
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载,除了本身的,它所依赖的也能找到 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
(3)resources下创建dubbo.properties
dubbo.application=manager
5. 青橙管理后台-品牌管理后端
5.1 需求分析
实现对品牌的基本操作(增删改查),只完成后端代码部分,并通过浏览器等工具完成
测试。
5.2 表结构分析
tb_brand 品牌表
就是品牌类别,图片地址时品牌的logo
5.3 代码实现
5.3.1 品牌列表
url
/brand/findAll.do
http请求方式
GET
返回格式
[{
"id": 品牌id,
"name": 品牌名称,
"image": 品牌图片地址,
"letter": 品牌的首字母,
"seq": 排序,
},
.......
]
代码实现:
(1)在qingcheng_pojo工程创建com.qingcheng.pojo包,包下创建实体类
@Table(name="tb_brand")
public class Brand implements Serializable{
@Id
private Integer id;//品牌id
private String name;//品牌名称
private String image;//品牌图片地址
private String letter;//品牌的首字母
private Integer seq;//排序
// getter and setter ......
}
(2)qingcheng_service_goods工程创建com.qingcheng.dao,包下创建数据访问层接
口
/*数据访问层,dao*/
public interface BrandMapper extends Mapper<Brand> {
}
(3)qingcheng_interface工程创建com.qingcheng.service.goods包,包下创建业务接
口
/**
* 品牌业务逻辑层
*/
public interface BrandService {
public List<Brand> findAll();
}
(4)qingcheng_service_goods工程创建com.qingcheng.service.impl包,包下创建类
@Service
public class BrandServiceImpl implements BrandService {
@Autowired
private BrandMapper brandMapper;
public List<Brand> findAll() {
return brandMapper.selectAll();
}
}
(5)qingcheng_web_manager工程创建com.qingcheng.controller.goods 包,包下创
建类
@RestController
@RequestMapping("/brand")
public class BrandController {
@Reference
/*注入远程的业务接口*/
private BrandService brandService;
@GetMapping("/findAll")
public List<Brand> findAll(){
return brandService.findAll();
}
}
测试
开启,可以在虚拟机中,也可以本机,zk
安装inferface,pojo
如果变化也要重新安装
开启service的tomcat7 run,开启,开启manager的tomcat7
浏览器输入:http://localhost:9101/brand/findAll.do
数据库返回数据,调用成功
5.3.2 品牌分页列表
接口定义:
url
/brand/findPage.do
http请求方式
GET
请求参数
例子:
GET /brand/findPage.do?page=1&size=10
返回格式
{
rows:[{
"id": 品牌id,
"name": 品牌名称,
"image": 品牌图片地址,
"letter": 品牌的首字母,
"seq": 排序,
},
.......
],
total:100}
pojo是和数据库对应的类,entity是自己封装的类,实现自定义数据模块
创建类pojo,创建功能接口interface,创建实现manager,分步实现
代码实现:
(1)qingcheng_pojo创建com.qingcheng.entity包,包下创建类
用来承载分页查询的对象
/**
* 分页结果
* @param <T>
*/
public class PageResult<T> implements Serializable {
private Long total;//记录数
private List<T> rows;//结果集
public PageResult(Long total, List<T> rows) {
this.total = total;
this.rows = rows;
}
public PageResult() {
}
public Long getTotal() {
return total;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
public void setTotal(Long total) {
this.total = total;
}
}
(2)qingcheng_interface工程BrandService接口新增方法
public PageResult<Brand> findPage(int page, int size);
(3)qingcheng_service_goods工程BrandServiceImpl新增方法
/**
* 分页查询
* @param page 页码
* @param size 每页记录数
* @return 分页结果
*/
public PageResult<Brand> findPage(int page, int size) {
PageHelper.startPage(page,size);
Page<Brand> brands = (Page<Brand>) brandMapper.selectAll();
return new PageResult<Brand>
(brands.getTotal(),brands.getResult());
}
(4)qingcheng_web_manager工程BrandController新增方法
@GetMapping("/findPage")
public PageResult<Brand> findPage(int page, int size){
return brandService.findPage(page, size);
}
因为更新了interface与pojo,所以需要重新安装
启动工程,浏览器测试:http://localhost:9101/brand/findPage.do?page=1&size=10
5.3.3 品牌条件查询
url
/brand/findList.do
http请求方式
POST
请求参数
例子:
POST /brand/findList.do
{
"name": 品牌名称,
"letter": 品牌的首字母
}
返回格式
[{
"id": 品牌id,
"name": 品牌名称,
"image": 品牌图片地址,
"letter": 品牌的首字母,
"seq": 排序,
},
.......
]
代码实现:
(1)qingcheng_interface工程BrandService接口新增方法
public List<Brand> findList(Map<String, Object> searchMap);
(2)qingcheng_service_goods工程BrandServiceImpl新增方法
/**
* 条件查询
* @param searchMap 查询条件
* @return
*/
public List<Brand> findList(Map<String, Object> searchMap) {
Example example = createExample(searchMap);
return brandMapper.selectByExample(example);
}
/**
* 构建查询条件
* @param searchMap
* @return
*/
private Example createExample(Map<String, Object> searchMap){
Example example=new Example(Brand.class);
Example.Criteria criteria = example.createCriteria();
if(searchMap!=null){
//名称条件
if(searchMap.get("name")!=null &&
!"".equals(searchMap.get("name"))){
criteria.andLike("name","%"+
(String)searchMap.get("name")+"%");
}
//首字母
if(searchMap.get("letter")!=null &&
!"".equals(searchMap.get("letter"))){
criteria.andEqualTo("letter",
(String)searchMap.get("letter"));
}
}
return example;
}
(3)qingcheng_web_manager工程BrandController新增方法
@PostMapping("/findList")
/*加入注解,分解请求得到的json数据*/
/*之前都是get请求的,输入条件参数,现在post请求*/
public List<Brand> findList( @RequestBody Map searchMap){
return brandService.findList(searchMap);
}
/之前都是get请求的,输入条件参数,现在post请求/
使用postman
以json方式请求,
多个条件加逗号即可
5.3.4 品牌条件+分页查询
写一个功能函数囊括以上两个功能即可
url
/brand/findPage.do
http请求方式
POST
请求参数
例子:
POST /brand/findPage.do?page=1&size=10
{
"name": 品牌名称,
"letter": 品牌的首字母
}
返回格式:
{
rows:[{
"id": 品牌id,
"name": 品牌名称,
"image": 品牌图片地址,
"letter": 品牌的首字母,
"seq": 排序
},
.......
],
total:100}
代码实现:
(1)qingcheng_interface工程BrandService接口新增方法
public PageResult<Brand> findPage(Map<String,Object> searchMap,int page,
int size);
(2)qingcheng_service_goods工程BrandServiceImpl新增方法
/**
* 分页+条件查询
* @param searchMap
* @param page
* @param size
* @return
*/
public PageResult<Brand> findPage(Map<String, Object> searchMap, int
page, int size) {
PageHelper.startPage(page,size);
Example example = createExample(searchMap);
Page<Brand> brands = (Page<Brand>)
brandMapper.selectByExample(example);
return new PageResult<Brand>
(brands.getTotal(),brands.getResult());
}
(3)qingcheng_web_manager工程BrandController新增方法
@PostMapping("/findPage")
public PageResult<Brand> findPage(@RequestBody Map<String,Object>
searchMap,int page, int size){
return brandService.findPage(searchMap,page,size);
}
使用了多态,将findPage执行了分页与条件的多次编写
5.3.5 根据ID查询品牌
url
/brand/findById.do
http请求方式
GET
请求参数
代码实现:
(1)qingcheng_interface工程BrandService接口新增方法
public Brand findById(Integer id);
(2)qingcheng_service_goods工程BrandServiceImpl新增方法
接口,实现,网址映射
/**
* 根据Id查询
* @param id
* @return
*/
public Brand findById(Integer id) {
return brandMapper.selectByPrimaryKey(id);
}
(3)qingcheng_web_manager工程BrandController新增方法
@GetMapping("/findById")
public Brand findById(Integer id){
return brandService.findById(id);
}
5.3.6 品牌新增
(1)qingcheng_pojo 新增类
/**
* 返回前端的消息封装,正确错误都有信息了
*/
public class Result implements Serializable {
private Integer code;//返回的业务码 0:成功执行 1:发生错误
private String message;//信息
public Result(Integer code, String message) {
this.code = code;
this.message = message;
}
public Result() {
this.code=0;
this.message = "执行成功";
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
(2)qingcheng_interface工程BrandService接口新增方法
public void add(Brand brand);
(3)qingcheng_service_goods工程BrandServiceImpl新增方法
/**
* 新增
* @param brand
*/
public void add(Brand brand) {
brandMapper.insert(brand);
}
(4)qingcheng_web_manager工程BrandController新增方法
@PostMapping("/add")
public Result add(@RequestBody Brand brand){
brandService.add(brand);
return new Result();
}
5.3.7 品牌修改
对于修改的方法,
第一个根据条件更新,第二个是如果有null值会被忽略,如果包含null值会被覆盖还是忽略,第四个为忽略,更加实用,不覆盖该数据库原来的数据
(1)qingcheng_interface工程BrandService接口新增方法
public void update(Brand brand);
(2)qingcheng_service_goods工程BrandServiceImpl新增方法
/**
* 修改
* @param brand
*/
public void update(Brand brand) {
brandMapper.updateByPrimaryKeySelective(brand);
}
(3)qingcheng_web_manager工程BrandController新增方法
@PostMapping("/update")
public Result update(@RequestBody Brand brand){
brandService.update(brand);
return new Result();
}
5.3.8 品牌删除
url
/brand/delete.do
http请求方式
GET
请求参数
例子:
GET /brand/delete.do?id=1
返回格式:
{
code:0,
message:""
}
code为0表示成功,为1表示失败
代码实现:
(1)qingcheng_interface工程BrandService接口新增方法
public void delete(Integer id);
(2)qingcheng_service_goods工程BrandServiceImpl新增方法
/**
* 删除
* @param id
*/
public void delete(Integer id) {
brandMapper.deleteByPrimaryKey(id);
}
(3)qingcheng_web_manager工程BrandController新增方法
@GetMapping("/delete")
public Result delete(Integer id){
brandService.delete(id);
return new Result();
}
以上主要是为了尝试,通用mapper的方法
6. 公共异常处理
应该将项目所有的异常,进行统一管理
qingcheng_common_web工程创建com.qingcheng.controller包,包下创建类
/**
* 统一异常处理类
*/
@ControllerAdvice
public class BaseExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Result error(Exception e) {
e.printStackTrace();
System.out.println("调用了公共异常处理类");
return new Result(1,e.getMessage());
}
}
注意回顾系统架构图,所有的都是围绕其展开
转载:https://blog.csdn.net/lidashent/article/details/115659185