1. 程式人生 > >微服務電商系統

微服務電商系統

 

電商系統架構

使用新技術介紹

專案環境搭建

工具類的封裝

 

專案介紹

微信商城+微信公眾號開發,該專案根據上海某大型知名電商企業網際網路網際網路專案,改版而來,使用最新微服務技術,頁面使用高仿小米介面。功能包含電商模組,會員、SSO、訂單、商品、支付、訊息、微信、H5和PC、移動端、優惠券、後臺系統、任務排程模組。

電商系統特點

1.技術新

2.技術範圍廣

3.分散式

4.高併發、叢集、負載均衡、高併發

5.海量資料

6.業務複雜

7.系統安全

電商系統架構

 

專案演變過程

 

傳統架構

分散式架構

什麼是分散式?

根據業務需求進行拆分成N個子系統,多個子系統相互協作才能完成業務流程子系統之間通訊使用RPC遠端通訊技術。

什麼叢集

同一個工程部署在多個不同的伺服器上。

分散式架構優點

1.把模組拆分,使用介面通訊,降低模組之間的耦合度。

2.把專案拆分成若干個子專案,不同的團隊負責不同的子專案。

3.增加功能時只需要再增加一個子專案,呼叫其它系統的介面就可以。

4.可以靈活的進行分散式部署。

有優點就有缺點,缺點如下:

1.系統之間互動需要使用遠端通訊,介面開發增加工作量。

2.各個模組有一些通用的業務邏輯無法共用。

為了解決上面分散式架構的缺點,我們引入了soa架構,SOA:Service Oriented Architecture面向服務的架構。也就是把工程拆分成服務層、表現層兩個工程。服務層中包含業務邏輯,只需要對外提供服務即可。表現層只需要處理和頁面的互動,業務邏輯都是呼叫服務層的服務來實現。

專案拆分

在大型電商專案中,會將一個的專案拆分成N多個子模組,分配給不同的團隊開發。

團隊之間通訊採用RPC遠端呼叫技術、使用Http+Restful+Json傳輸

介面服務

會員服務、訂單服務、商品服務、支付服務、訊息

服務、秒殺服務、優惠券服務

專案工程

H5專案、微信專案、後臺管理

 

使用技術

電商專案

SpringBoot+SpringCloud +Maven+Redis+ActiveMQ+XXLJOB(分散式任務排程)+ Freemarker等。

使用 SpringCloud Eureka作為註冊中心、Feign客戶端呼叫工具、斷路器Hystrix

檢視展示使用Freemarker、資料庫層使用Mybatis框架、快取使用Redis、資料庫使用MySQL

專案管理工具使用Maven、版本控制工具使用SVN、專案自動部署工具使用Jenkins

訊息中間使用ActiveMQ、分散式任務排程系統使用XXLJOB、反向代理工具使用Nginx

日誌管理外掛工具使用lombok、分散式日誌收集使用Logstash、解析JSON框架使用FastJson

資料安全加密使用MD5加鹽和Base64、RSA、分散式檔案儲存系統FastDFS等。

支付閘道器介面使用支付寶、第三方登入使用QQ授權等

專案構建

itmayiedu-shopp-parent

├─itmayiedu-shopp-common                 // 抽取的公共模組

├─itmayiedu-shopp-eurekaserver             // eureka註冊中心

├─itmayiedu-shopp-api                      // api服務              

   ├─itmayiedu-shopp-member-api          // 會員服務

├─itmayiedu-shopp-order-api            // 訂單服務

├─itmayiedu-shopp-goods-api           // 商品服務

├─itmayiedu-shopp-pay-api             // 支付服務

├─itmayiedu-shopp-member                // 會員系統

├─itmayiedu-shopp-nessage                 // 訊息系統

├─itmayiedu-shopp-mobile-web             // h5端工程

 

建立Modules

 

環境搭建

 

環境搭建步驟

建立專案

引入依賴

搭建eureka註冊中心

封裝控制層、日誌、常量、常用工具、Basedao

 

itmayiedu-shopp-parent

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.3.RELEASE</version>

</parent>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>

</properties>

<dependencies>

<!-- 整合commons工具類 -->

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-lang3</artifactId>

<version>3.4</version>

</dependency>

<!-- 整合lombok 框架 -->

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

<!-- 整合redis -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

<!-- 整合aop -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-aop</artifactId>

</dependency>

<!-- 整合web-->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!-- springboot整合activemq -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-activemq</artifactId>

</dependency>

<!-- 整合傳送郵件-->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-mail</artifactId>

</dependency>

<!-- 整合mysql -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>



<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.4.0</version>

</dependency>

<dependency>

<groupId>tk.mybatis</groupId>

<artifactId>mapper</artifactId>

<version>3.3.7</version>

</dependency>

<!-- 阿里巴巴資料來源 -->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.0.14</version>

</dependency>

<!-- httpclient -->

<dependency>

<groupId>commons-httpclient</groupId>

<artifactId>commons-httpclient</artifactId>

<version>3.1</version>

</dependency>

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpclient</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>fastjson</artifactId>

<version>1.2.30</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

</dependency>

<dependency>

<groupId>commons-net</groupId>

<artifactId>commons-net</artifactId>

<version>3.3</version>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-eureka-server</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-feign</artifactId>

</dependency>



</dependencies>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.RC1</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

<repositories>

<repository>

<id>spring-milestones</id>

<name>Spring Milestones</name>

<url>https://repo.spring.io/milestone</url>

<snapshots>

<enabled>false</enabled>

</snapshots>

</repository>

</repositories>

itmayiedu-shopp-common

Maven依賴

<parent>

<groupId>com.itmayiedu</groupId>

<artifactId>itmayiedu-shopp-parent</artifactId>

<version>0.0.1-SNAPSHOT</version>

</parent>

<artifactId>itmayiedu-shopp-common</artifactId>



<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

</dependencies>

 

 

 

itmayiedu-shopp-eurekaserver

Maven依賴

<parent>

    <groupId>com.itmayiedu</groupId>

    <artifactId>itmayiedu-shopp-parent</artifactId>

    <version>0.0.1-SNAPSHOT</version>

  </parent>

  <groupId>com.itmayiedu</groupId>

  <artifactId>itmayiedu-shopp-eurekaservers</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

啟動EureKaServer

建立eureka作為服務註冊中心

@SpringBootApplication

@EnableEurekaServer

public class EureKaServer {



public static void main(String[] args) {

SpringApplication.run(EureKaServer.class, args);

}

}

 

application.yml

server:

  port: 8761

eureka:

  instance:

    hostname: localhost

  client:

    registerWithEureka: false

    fetchRegistry: false

    serviceUrl:

      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

itmayiedu-shopp-api

建立itmayiedu-shopp-api工程,存放所有的需要提供給外部介面項

itmayiedu-shopp-member-api

建立MemberService測試介面

@RequestMapping("/member")

public interface MemberService {

@RequestMapping("/testRest")

public Map<String, Object> testRest();

}

 

itmayiedu-shopp-member

Maven依賴

<dependencies>

<dependency>

<groupId>com.itmayiedu</groupId>

<artifactId>itmayiedu-shopp-member-api</artifactId>

<version>0.0.1-SNAPSHOT</version>

</dependency>

<dependency>

<groupId>com.itmayiedu</groupId>

<artifactId>itmayiedu-shopp-common</artifactId>

<version>0.0.1-SNAPSHOT</version>

</dependency>

<!-- springboot整合mybatis -->

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.3.0</version>

</dependency>



</dependencies>

配置檔案

server:

  port: 8762

#  context-path: /member

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

spring:

  application:

    name: member

實現介面MemberServiceImpl

@RestController

public class MemberServiceImpl implements MemberService {



@Override

public Map<String, Object> testRest() {

Map<String, Object> result = new HashMap<>();

result.put("errorCode", "200");

result.put("errorMsg", "success");

return result;

}



}

 

 

工具類封裝

建立ResponseBase

public class ResponseBase {

// 響應code

private Integer code;

// 訊息內容

private String msg;

// 返回data

private Object data;


public ResponseBase() {

}


public ResponseBase(Integer code, String msg, Object data) {

super();

this.code = code;

this.msg = msg;

this.data = data;

}

public Integer getCode() {

return code;

}

public void setCode(Integer code) {

this.code = code;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

public Object getData() {

return data;

}


public void setData(Object data) {

this.data = data;

}

}

 

BaseController

public class BaseController {


// 返回成功 ,data值為null

public ResponseBase setResultSuccess() {

return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, null);

}

// 返回成功 ,data可傳

public ResponseBase setResultSuccess(Object data) {

return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, data);

}

// 返回失敗

public ResponseBase setResultError(String msg){

return setResult(Constants.HTTP_RES_CODE_500,msg, null);

}

// 自定義返回結果

public ResponseBase setResult(Integer code, String msg, Object data) {

ResponseBase responseBase = new ResponseBase();

responseBase.setCode(code);

responseBase.setMsg(msg);

if (data != null)

responseBase.setData(data);

return responseBase;

}

}

 

ListUtils封裝

public class ListUtils {



//判斷list集合是否為空

public List<?> emptyList(List<?> list) {

if (list == null || list.size() <= 0) {

return null;

}

return list;

}

//判斷map集合是否為空

public Map<?,?> emptyMap(Map<?,?> map) {

if (map == null || map.size() <= 0) {

return null;

}

return map;

}

}

Constants

public interface Constants {

// 響應code

String HTTP_RES_CODE_NAME = "code";

// 響應msg

String HTTP_RES_CODE_MSG = "msg";

// 響應data

String HTTP_RES_CODE_DATA = "data";

// 響應請求成功

String HTTP_RES_CODE_200_VALUE = "success";

// 系統錯誤

String HTTP_RES_CODE_500_VALUE = "fial";

// 響應請求成功code

Integer HTTP_RES_CODE_200 = 200;

// 系統錯誤

Integer HTTP_RES_CODE_500 = 500;

}

 

BaseRedis

@SuppressWarnings({ "rawtypes", "unchecked" })

@Component

public class BaseRedisService {

@Autowired

private StringRedisTemplate stringRedisTemplate;

public void setString(String key, Object data, Long timeout) {

if (data instanceof String) {

String value = (String) data;

stringRedisTemplate.opsForValue().set(key, value);

}

if (timeout != null) {

stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);

}

}

public Object getString(String key) {

return stringRedisTemplate.opsForValue().get(key);

}

public void delKey(String key) {

stringRedisTemplate.delete(key);

}

}

 

Linux環境下安裝redis

 linux 安裝redis

Redis的官方下載網址是:http://redis.io/download  (這裡下載的是Linux版的Redis原始碼包)

Redis伺服器端的預設埠是6379。

這裡以虛擬機器中的Linux系統如何安裝Redis進行講解。

 在windows系統中下載好Redis的原始碼包。

1. 通過WinSCP工具,將Redis的原始碼包由windows上傳到Linux系統的這個目錄/opt/redis (即根目錄下的lamp資料夾)。

2. 解壓縮。           

tar -zxf redis-2.6.17.tar.gz

3. 切換到解壓後的目錄。

cd redis-2.6.17            ( 一般來說,解壓目錄裡的INSTALL檔案或README檔案裡寫有安裝說明,可參考之)

4. 編譯。

make        

(注意,編譯需要C語言編譯器gcc的支援,如果沒有,需要先安裝gcc。可以使用rpm -q gcc檢視gcc是否安裝)

(利用yum線上安裝gcc的命令    yum -y install gcc )

(如果編譯出錯,請使用make clean清除臨時檔案。之後,找到出錯的原因,解決問題後再來重新安裝。 )

5. 進入到src目錄。       

cd src

6. 執行安裝。

make install    

到此就安裝完成。但是,由於安裝redis的時候,我們沒有選擇安裝路徑,故是預設位置安裝。在此,我們可以將可執行檔案和配置檔案移動到習慣的目錄。

cd /usr/local

mkdir -p /usr/local/redis/bin    

mkdir -p /usr/local/redis/etc

cd /lamp/redis-2.6.17

mv ./redis.conf /usr/local/redis/etc

cd src

mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server redis-sentinel /usr/local/redis/bin

7.開放linux 6379

1.編輯 /etc/sysconfig/iptables 檔案:vi /etc/sysconfig/iptables
加入內容並儲存:-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 6379 -j ACCEPT
2.重啟服務:/etc/init.d/iptables restart
3.檢視埠是否開放:/sbin/iptables -L -n

比較重要的3個可執行檔案:

redis-server:Redis伺服器程式

redis-cli:Redis客戶端程式,它是一個命令列操作工具。也可以使用telnet根據其純文字協議操作。

redis-benchmark:Redis效能測試工具,測試Redis在你的系統及配置下的讀寫效能。

Redis的啟動命令:

/usr/local/redis/bin/redis-server

cd /usr/local/redis/bin

./redis-server /usr/local/redis/etc/redis.conf    為redis-server指定配置檔案

修改 redis.conf檔案

daemonize yes --- 修改為yes  後臺啟動

requirepass 123456  ----註釋取消掉設定賬號密碼

ps aux | grep '6379'  --- 查詢埠

kill -15 9886 --- 殺死重置

kill -9 9886 --- 強制殺死

service iptables stop 停止防火牆

 redis命令連線方式

./redis-cli -h 127.0.0.1 -p 6379 -a "123456"  --- redis 使用賬號密碼連線

PING 結果表示成功

SpringBoot整合Redis

步驟引入依賴

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

Redis封裝Java

在itmayiedu-shopp-common專案下建立一個BaseRedisService

@Component

public class BaseRedisService {

@Autowired

private StringRedisTemplate stringRedisTemplate;

public void setString(String key, Object data) {

setString(key, data, null);

}

public void setString(String key, Object data, Long timeout) {

if (data instanceof String) {

String value = (String) data;

stringRedisTemplate.opsForValue().set(key, value);

}

if (timeout != null) {

stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);

}

}



public String getString(String key) {

return (String) stringRedisTemplate.opsForValue().get(key);

}

public void delKey(String key) {

stringRedisTemplate.delete(key);

}

}

配置檔案新增redis連線

spring:

  redis:

    host: 127.0.0.1

    password: 123456

    port: 6379

    pool:

      max-idle: 100

      min-idle: 1

      max-active: 1000

      max-wait: -1

測試結果

MemberService

@RequestMapping("/setRedisTest")

public ResponseBase setRedisTest(String key, String value);

@RequestMapping("/getRedis")

public ResponseBase getRedis(String key);

MemberServiceImpl


@Override

public ResponseBase setRedisTest(String key, String value) {

baseRedisService.setString(key, value);

return setResultSuccess();

}



@Override

public ResponseBase getRedis(String key) {

String value = baseRedisService.getString(key);

return setResultSuccess(value);

}

 

 

日誌

安裝lomBok外掛

1.下載lombok.jar包https://projectlombok.org/download.html

2.執行Lombok.jar: Java -jar D:\software\lombok.jar D:\software\lombok.jar這是windows下lombok.jar所在的位置

數秒後將彈出一框,以確認eclipse的安裝路徑</code>

3.確認完eclipse的安裝路徑後,點選install/update按鈕,即可安裝完成

4.安裝完成之後,請確認eclipse安裝路徑下是否多了一個lombok.jar包,並且其

 

配置檔案eclipse.ini中是否 添加了如下內容: </code>

-javaagent:lombok.jar

    -Xbootclasspath/a:lombok.jar

那麼恭喜你已經安裝成功,否則將缺少的部分新增到相應的位置即可 </code>

  1. 重啟eclipse或myeclipse

 

Lombok作用

使用註解版本,生成get和set方法、簡化重複程式碼

Maven座標

<!-- 整合lombok 框架 -->

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

生成get或set方法

@Getter

public class TestEntity {

private String userId;

private String userName;

// public String getUserId() {

//

// return userId;

// }

// public void setUserId(String userId) {

//

// this.userId = userId;

// }

// public String getUserName() {

//

// return userName;

// }

// public void setUserName(String userName) {

//

// this.userName = userName;

// }

public static void main(String[] args) {

 //使用

 new TestEntity().getUserId();

}



}

 

列印日誌

@Slf4j

@RestController

public class MemberServiceImpl extends BaseApiRedisService implements MemberService {



@Autowired

private BaseRedisService baseRedisService;



@Override

public Map<String, Object> index() {

String result = "644064";

log.info("request .... index result:{}",result);

return setResultData(result);

}

}

使用aop列印請求引數

@Aspect

// 申明是個spring管理的bean

@Component

@Slf4j

public class LogAspectServiceApi {

private JSONObject jsonObject = new JSONObject();



// 申明一個切點 裡面是 execution表示式

@Pointcut("execution(public * com.itmayiedu.service.*.*(..))")

private void controllerAspect() {

}



// 請求method前列印內容

@Before(value = "controllerAspect()")

public void methodBefore(JoinPoint joinPoint) {

ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder

.getRequestAttributes();

HttpServletRequest request = requestAttributes.getRequest();

log.info("===============請求內容===============");

try {

// 列印請求內容

log.info("請求地址:" + request.getRequestURL().toString());

log.info("請求方式:" + request.getMethod());

log.info("請求類方法:" + joinPoint.getSignature());

log.info("請求類方法引數:" + Arrays.toString(joinPoint.getArgs()));

} catch (Exception e) {

log.error("###LogAspectServiceApi.class methodBefore() ### ERROR:", e);

}

log.info("===============請求內容===============");

}



// 在方法執行完結後列印返回內容

@AfterReturning(returning = "o", pointcut = "controllerAspect()")

public void methodAfterReturing(Object o) {

log.info("--------------返回內容----------------");

try {

log.info("Response內容:" + jsonObject.toJSONString(o));

} catch (Exception e) {

log.error("###LogAspectServiceApi.class methodAfterReturing() ### ERROR:", e);

}

log.info("--------------返回內容----------------");

}

}

 

日誌收集

 

 

 

DateUtils

@Slf4j

public class DateUtils {



/** 年-月-日 時:分:秒 顯示格式 */

// 備註:如果使用大寫HH標識使用24小時顯示格式,如果使用小寫hh就表示使用12小時制格式。

public static String DATE_TO_STRING_DETAIAL_PATTERN = "yyyy-MM-dd HH:mm:ss";



/** 年-月-日 顯示格式 */

public static String DATE_TO_STRING_SHORT_PATTERN = "yyyy-MM-dd";



private static SimpleDateFormat simpleDateFormat;



/**

 * Date型別轉為指定格式的String型別

 *

 * @param source

 * @param pattern

 * @return

 */

public static String DateToString(Date source, String pattern) {

simpleDateFormat = new SimpleDateFormat(pattern);

return simpleDateFormat.format(source);

}



/**

 *

 * unix時間戳轉為指定格式的String型別

 *

 *

 * System.currentTimeMillis()獲得的是是從1970年1月1日開始所經過的毫秒數

 * unix時間戳:是從1970年1月1日(UTC/GMT的午夜)開始所經過的秒數,不考慮閏秒

 *

 * @param source

 * @param pattern

 * @return

 */

public static String timeStampToString(long source, String pattern) {

simpleDateFormat = new SimpleDateFormat(pattern);

Date date = new Date(source * 1000);

return simpleDateFormat.format(date);

}



/**

 * 將日期轉換為時間戳(unix時間戳,單位秒)

 *

 * @param date

 * @return

 */

public static long dateToTimeStamp(Date date) {

Timestamp timestamp = new Timestamp(date.getTime());

return timestamp.getTime() / 1000;



}



/**

 *

 * 字串轉換為對應日期(可能會報錯異常)

 *

 * @param source

 * @param pattern

 * @return

 */

public static Date stringToDate(String source, String pattern) {

simpleDateFormat = new SimpleDateFormat(pattern);

Date date = null;

try {

date = simpleDateFormat.parse(source);

} catch (ParseException e) {

log.error("字串轉換日期異常", e);

}

return date;

}



/**

 * 獲得當前時間對應的指定格式

 *

 * @param pattern

 * @return

 */

public static String currentFormatDate(String pattern) {

simpleDateFormat = new SimpleDateFormat(pattern);

return simpleDateFormat.format(new Date());



}



/**

 * 獲得當前unix時間戳(單位秒)

 *

 * @return 當前unix時間戳

 */

public static long currentTimeStamp() {

return System.currentTimeMillis() / 1000;

}

/**

 *

 * @methodDesc: 功能描述:(獲取當前系統時間戳)

 * @param: @return

 */

public static Timestamp getTimestamp() {

          return new Timestamp(new Date().getTime());

}



// 待補充

MD5Util

public class MD5Util {  

  

    public final static String MD5(String s) {  

        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};         

        try {  

            byte[] btInput = s.getBytes();  

            // 獲得MD5摘要演算法的 MessageDigest 物件  

            MessageDigest mdInst = MessageDigest.getInstance("MD5");  

            // 使用指定的位元組更新摘要  

            mdInst.update(btInput);  

            // 獲得密文  

            byte[] md = mdInst.digest();  

            // 把密文轉換成十六進位制的字串形式  

            int j = md.length;  

            char str[] = new char[j * 2];  

            int k = 0;  

            for (int i = 0; i < j; i++) {  

                byte byte0 = md[i];  

                str[k++] = hexDigits[byte0 >>> 4 & 0xf];  

                str[k++] = hexDigits[byte0 & 0xf];  

            }  

            return new String(str);  

        } catch (Exception e) {  

            e.printStackTrace();  

            return null;  

        }  

    }  

    public static void main(String[] args) {  

        System.out.println(MD5Util.MD5("20121221"));  

        System.out.println(MD5Util.MD5("加密"));  

    }  

}  

 

 

 

BaseDao

maven依賴

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.4.0</version>

</dependency>

<dependency>

<groupId>tk.mybatis</groupId>

<artifactId>mapper</artifactId>

<version>3.3.7</version>

</dependency>

<!-- springboot整合mybatis -->

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.3.0</version>

</dependency>

資料來源連線

spring:

  application:

    name: member

  #redis連線資訊

  redis:

    host: 192.168.110.163

    password: 123456

    port: 6379

    pool:

      max-idle: 100

      min-idle: 1

      max-active: 1000

      max-wait: -1

  #資料庫連線資訊

  datasource:

        name: test

        url: jdbc:mysql://127.0.0.1:3306/itmayiedu-member

        username: root

        password: root

        # 使用druid資料來源

        type: com.alibaba.druid.pool.DruidDataSource

        driver-class-name: com.mysql.jdbc.Driver

        filters: stat

        maxActive: 20

        initialSize: 1

        maxWait: 60000

        minIdle: 1

        timeBetweenEvictionRunsMillis: 60000

        minEvictableIdleTimeMillis: 300000

        validationQuery: select 'x'

        testWhileIdle: true

        testOnBorrow: false

        testOnReturn: false

        poolPreparedStatements: true

        maxOpenPreparedStatements: 20

 

 

建立Baseentity

 

@Getter

@Setter

public class BaseEntity {



/**

 * 主鍵ID

 */

private Long id;

/**

 * 建立時間

 */

private Timestamp     created;

/**

 * 修改時間

 */

private Timestamp     updated;





}

 

 

建立Basedao

/**

 *

 * @classDesc: 功能描述:(BaseDao)

 */

public interface BaseDao {



/**

 *

 *

 * @methodDesc: 功能描述:(增加持久化物件)

 * @param: @param

 *             t

 */

@InsertProvider(type = BaseProvider.class, method = "save")

public void save(@Param("oj") Object oj, @Param("table") String table);



/**

 *

 *

 * @methodDesc: 功能描述:(修改持久化物件)

 * @param: @param

 *             t

 * @return

 */

@InsertProvider(type = BaseProvider.class, method = "update")

public void update(@Param("oj") Object oj, @Param("table") String table, @Param("idKey") Long idKey);



}

 

建立BaseProvider

public class BaseProvider {



public String save(Map<String, Object> para) {

final Object oj = para.get("oj");

final String table = (String) para.get("table");

String sql = new SQL() {

{

INSERT_INTO(table);

String columns = ReflectionUtils.getInsertFields(oj);

String values = ReflectionUtils.getInsertDeclaredFieldsValue(oj);

VALUES(columns, values);

}

}.toString();

return sql;

}



public String update(Map<String, Object> para) {

final Object oj = para.get("oj");

final String table = (String) para.get("table");

final Long idKey = (Long) para.get("idKey");

String sql = new SQL() {

{

UPDATE(table);

SET(ReflectionUtils.updateAllSerField(oj));

WHERE("id="+idKey + "");

}

}.toString();

return sql;

}



}

 

建立ReflectionUtils工具

/**

 *

 * @classDesc: 功能描述:(Java反射工具類)



 */

@Slf4j

public class ReflectionUtils {



/**

 *

 * @methodDesc: 功能描述:(獲取類的屬性,拼接成字串)

 * @param: @return

 */

public static String getInsertFields(Object oj) {

if (oj == null) {

return null;

}

Class cl = oj.getClass();

// 獲取所有的屬性

Field[] declaredFields = cl.getDeclaredFields();

String sb1 = appendFields(declaredFields);

Class superclass = cl.getSuperclass();

Field[] superField = superclass.getDeclaredFields();

String sb2 = appendFields(superField);

return sb1 + "," + sb2;

}



/**

 *

 * @methodDesc: 功能描述:(獲取類的屬性,拼接成字串的值)

 * @param: @return

 * @throws IllegalAccessException

 * @throws IllegalArgumentException

 * @throws InstantiationException

 */

public static String getInsertDeclaredFieldsValue(Object oj) {

if (oj == null) {

return null;

}

Class cl = oj.getClass();

// 獲取所有的屬性

Field[] declaredFields = cl.getDeclaredFields();

String sb1 = appendFieldValues(declaredFields, oj);

Class superclass = cl.getSuperclass();

Field[] superField = superclass.getDeclaredFields();

String sb2 = appendFieldValues(superField, oj);

return sb1 + "," + sb2;

}



/**

 *

 * @methodDesc: 功能描述:(獲取類的屬性,拼接成字串值)

 * @param: @param

 *             oj

 * @param: @return

 */

public static String updateAllSerField(Object oj) {

if (oj == null) {

return null;

}

Class cl = oj.getClass();

// 獲取所有的屬性

Field[] declaredFields = cl.getDeclaredFields();

String sb1 = updateSerField(declaredFields, oj);

Field[] supDeclaredFields = cl.getSuperclass().getDeclaredFields();

String sb2 = updateSerField(supDeclaredFields, oj);

return sb1 + "," + sb2;

}



public static String updateSerField(Field[] declaredFields, Object oj) {

StringBuffer sb = new StringBuffer();

try {

for (int i = 0; i < declaredFields.length; i++) {

String name = declaredFields[i].getName();

if (name.equals("id")) {

continue;

}

declaredFields[i].setAccessible(true);

Object value = declaredFields[i].get(oj);

if (value == null) {

continue;

}

sb.append(name + "=" + "'" + value + "'");

if ((i < declaredFields.length - 1)) {

sb.append(",");

}

}

} catch (Exception e) {

log.error("###updateSerField() ERROR:", e);

}

return sb.toString();

}



 public static String appendFieldValues(Field[] declaredFields, Object oj) {

StringBuffer sf = new StringBuffer();

try {

for (int i = 0; i < declaredFields.length; i++) {

Field field = declaredFields[i];

String name = field.getName();

if (name == "id") {

continue;

}

field.setAccessible(true);// 設定私有許可權訪問

sf.append("'" + field.get(oj) + "'");

if (i < declaredFields.length - 1) {

sf.append(",");

}

}

} catch (Exception e) {

log.error("###ERROR:getDeclaredFieldsValue方法出現異常:", e);

}

return sf.toString();

}



 public static String appendFields(Field[] declaredFields) {

StringBuffer sf = new StringBuffer();

// 獲取到子類的

for (int i = 0; i < declaredFields.length; i++) {

Field field = declaredFields[i];

String name = field.getName();

if (name == "id") {

continue;

}

sf.append(field.getName());

if (i < declaredFields.length - 1) {

sf.append(",");

}

}

return sf.toString();

}



}

 

程式碼測試