1. 程式人生 > 實用技巧 >尚籌網09使用者註冊

尚籌網09使用者註冊

總體思路

建立資料庫表

create table t_member(
   id                   int(11) not null auto_increment,
   loginacct            varchar(255) not null,
   userpswd             char(200) not null,
   username             varchar(255),
   email                varchar(255),
   authstatus           tinyint(4) comment '
實名認證狀態 0 - 未實名認證, 1 - 實名認證申請中, 2 - 已實名認證', usertype tinyint(4) comment ' 0 - 個人, 1 - 企業', realname varchar(255), cardnum varchar(255), accttype tinyint(4) comment '0 - 企業, 1 - 個體, 2 - 個人, 3 - 政府', primary key (id));

api介面呼叫微服務service

傳送驗證碼

目標

1、將驗證碼傳送到使用者手機上

2、將驗證碼存入redis

思路

準備簡訊傳送API

匯入依賴

<!--ali簡訊-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.15</version>
</dependency>
<dependency>
    <groupId>commons-lang</
groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> <version>9.3.7.v20160115</version> </dependency>

加入HttpUtil

依賴

<!--阿里簡訊-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.15</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2.1</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.2.1</version>
</dependency>
<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-util</artifactId>
    <version>9.3.7.v20160115</version>
</dependency>

程式碼

package com.aliyun.api.gateway.demo.util;
public class HttpUtils {

    /**
     * get
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doGet(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request);
    }

    /**
     * post form
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param bodys
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      Map<String, String> bodys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();

            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }

        return httpClient.execute(request);
    }

    /**
     * Post String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    /**
     * Post stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }

    /**
     * Put String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    /**
     * Put stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }

    /**
     * Delete
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doDelete(String host, String path, String method,
                                        Map<String, String> headers,
                                        Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request);
    }

    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }

        return sbUrl.toString();
    }

    private static HttpClient wrapClient(String host) {
        HttpClient httpClient = new DefaultHttpClient();
        if (host.startsWith("https://")) {
            sslClient(httpClient);
        }

        return httpClient;
    }

    private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] xcs, String str) {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] xcs, String str) {

                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }
}

建立工具方法

/**
     * @param host     簡訊介面呼叫url地址
     * @param path     具體傳送簡訊地址
     * @param method   請求方法
     * @param phoneNum 手機號
     * @param appCode  應用碼
     * @param sign
     * @param skin
     * @return 成功返回驗證碼
     */
    public static ResultEntity<String> sendCodeByShortMessage(
            String host,
            String path,
            String method,
            String phoneNum,
            String appCode,
            String sign,
            String skin) {

        Map<String, String> headers = new HashMap<String, String>();
        //最後在header中的格式(中間是英文空格)為Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appCode);
        Map<String, String> querys = new HashMap<String, String>();
//        驗證碼
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < 4; i++) {
            int random = (int) (Math.random() * 10);
            stringBuilder.append(random);
        }
        String code = stringBuilder.toString();
        querys.put("param", code);
        querys.put("phone", phoneNum);
        querys.put("sign", sign);
        querys.put("skin", skin);
        //JDK 1.8示例程式碼請在這裡下載:  http://code.fegine.com/Tools.zip

        try {
            /**
             * 重要提示如下:
             * HttpUtils請從
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 或者直接下載:
             * http://code.fegine.com/HttpUtils.zip
             * 下載
             *
             * 相應的依賴請參照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             * 相關jar包(非pom)直接下載:
             * http://code.fegine.com/aliyun-jar.zip
             */
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
            //System.out.println(response.toString());如不輸出json, 請開啟這行程式碼,列印除錯頭部狀態碼。
            //狀態碼: 200 正常;400 URL無效;401 appCode錯誤; 403 次數用完; 500 API網管錯誤
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            String reasonPhrase = statusLine.getReasonPhrase();

            if (statusCode == 200) {
                return ResultEntity.sucessWithData(code);
            }
            return ResultEntity.failed(reasonPhrase);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }

    }

yml配置檔案讀取資料

匯入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

編寫配置檔案

編寫簡訊property

package com.adom.authentication.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Component
@ConfigurationProperties(prefix = "short.message")
public class ShortMessageProperties {
    // 呼叫簡訊傳送介面時的訪問地址
    private String host;
    // 具體訪問路徑
    private String path;
    // 請求方式
    private String method;
    // 登入阿里雲後,進入管理控制檯->雲市場->已購買服務,複製AppCode
    private String appCode;
    // 簽名編號
    private String sign;
    // 模板編號
    private String skin;

    public ShortMessageProperties() {
    }

    public ShortMessageProperties(String host, String path, String method, String appCode, String sign, String skin) {
        this.host = host;
        this.path = path;
        this.method = method;
        this.appCode = appCode;
        this.sign = sign;
        this.skin = skin;
    }

前端思路(忽略)

後端程式碼

建立傳送簡訊驗證碼的controller

1、先發送簡訊,若傳送成功,則把驗證碼加入到redis

@ResponseBody
@RequestMapping(value = "/auth/member/send/short/message.json", method = RequestMethod.POST)
public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum) {
    // 1.傳送驗證碼到手機
    ResultEntity<String> sendMeassageResultEntity = CrowdUtil.sendCodeByShortMessage(
            shortMessageProperties.getHost(),
            shortMessageProperties.getPath(),
            shortMessageProperties.getMethod(), phoneNum,
            shortMessageProperties.getAppCode(),
            shortMessageProperties.getSign(),
            shortMessageProperties.getSkin());
    // 2,判斷簡訊傳送的結果
    if (ResultEntity.SUCCESS.equals(sendMeassageResultEntity.getResult())) {
        // 3.如果傳送成功,則將驗證碼存入redis
        String code = sendMeassageResultEntity.getData();
        String key = ConstantUtil.REDIS_CODE_PREFIX + phoneNum;
        ResultEntity<String> saveCodeResultEntity = redisRemoteService.setRedisKeyValueRemoteWithTimeout(key, code, 15, TimeUnit.MINUTES);
        if (ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())) {
            return ResultEntity.successWithoutData();
        } else {
            return saveCodeResultEntity;
        }
    } else {
        return sendMeassageResultEntity;
    }
}

redis中儲存驗證碼資料的key

宣告redis-provider功能api

@FeignClient("adom-crowd-redis")
public interface RedisRemoteService {


    @RequestMapping("/set/redis/key/value/remote")
    ResultEntity<String> setRedisKeyValueRemote(
            @RequestParam("key") String key, @RequestParam("value") String value);

    @RequestMapping("/set/redis/key/value/remote/with/timeout")
    ResultEntity<String> setRedisKeyValueRemoteWithTimeout(
            @RequestParam("key") String key, @RequestParam("value") String value, @RequestParam("time") long time, @RequestParam("timeUnix") TimeUnit timeUnit);

    @RequestMapping("/get/redis/string/value/by/key")
    ResultEntity<String> getRedisStringValueByKeyRemote(@RequestParam("key") String key);

    @RequestMapping("/remove/redis/key/remote")
    ResultEntity<String> removeRedisKeyRemote(@RequestParam("key") String key);
}

Redis-provider功能實現

@RestController
public class RedisController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("set/redis/key/value/remote")
    ResultEntity<String> setRedisKeyValueRemote(
            @RequestParam("key") String key,
            @RequestParam("value")String value){
        try {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            operations.set(key,value);
            return ResultEntity.successWithoutData();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }
    }
    @RequestMapping("set/redis/key/value/remote/with/timeout")
    ResultEntity<String> setRedisKeyValueRemoteWithTimeout(
            @RequestParam("key") String key,
            @RequestParam("value")String value,
            @RequestParam("time") long time,
            @RequestParam("timeUnit") TimeUnit timeUnit){
        try {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            operations.set(key,value,time,timeUnit);
            return ResultEntity.successWithoutData();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }
    }
    @RequestMapping("get/redis/string/value/by/key")
    ResultEntity<String> getRedisStringValueByKey(@RequestParam("key") String key){
        try {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            String value = operations.get(key);
            return ResultEntity.sucessWithData(value);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }
    }

    @RequestMapping("remove/redis/key/remote")
    ResultEntity<String> removeRedisKeyRemote(@RequestParam("key") String key){
        try {
            redisTemplate.delete(key);
            return ResultEntity.successWithoutData();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }
    }

}

程式碼缺陷(未解決)

分散式事務

舉例

傳送簡訊操作和redis儲存操作在執行時都有可能失敗.如果發生其中一個操作失敗,另一個成功,那麼資料整體就會發生不一致的情況.

分析

如果是在以前關係型資料庫的事務操作中,可以採用回滾機制,一個事物多個操作中有任何

一個失敗,則整個事務全部回滾.

在分散式環境下,沒辦法將多個具體操作納入到一個統一的事務中,一起提交、一起回滾.

也不能使用逆操作手動撤銷,因為逆操作除了功能和原本操作不同,其他方面和原本的操作性質是一樣的.

解決方法

yml配置檔案讀取資料

加入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

yml配置

這些配置項全部都是自定義的,完全沒有框架的支援.

short:
  message:
    app-code: 303208760dc14fb994c6dfba5c82e1e6
    host: https://feginesms.market.alicloudapi.com
    method: GET
    path: /codeNotice
    sign: 1
    skin: 1

java類中引用方式

@Component
@ConfigurationProperties(prefix = "short.message")
public class ShortMessageProperties {

意義:以後在SpringBoot環境下開發時,如果某些資訊不能在java程式碼中寫死,就可以使用這樣的機制在yml配置檔案中配置,再使用@value註解讀取.ymlproperties檔案都可以.

執行註冊

流程分析

目標

如果針對註冊操作所做的各項驗證能夠通過,則將Member資訊存入資料庫.

思路

1、接受表單資料
    a)登陸賬號
    b)密碼
    c)手機號
    d)驗證碼
2、檢查驗證碼是否有效
    a)無效:返回失敗資訊,停止執行
    b)有效繼續執行
3、檢查手機號是否有效
    a)無效:返回失敗資訊,停止執行
    b)有效:繼續執行
4、拼接接收到驗證碼的key
5、呼叫redis-provider的api方法獲取對應的驗證碼值
    a)沒有查詢到值:返回失敗資訊,停止執行
    b)查詢到有效值:繼續執行
6、進行比較
    a)表單提交的驗證碼
    b)redis取回的驗證碼
7、不一致:返回失敗資訊,停止執行
8、一致
a)從redis中刪除當前key對應的驗證碼
b)繼續執行
9、呼叫資料庫api方法檢查登陸賬號是否被佔用
a)已經被佔用:返回失敗資訊,停止執行
b)沒有被佔用:繼續執行
10、密碼加密
11、呼叫資料庫api方法檢查登陸賬號是否被佔用

封裝MemberVO

public class MemberVO {
 private String loginAcct;
    private String userPswd;
    private String email;
    private String userName;
    private String phoneNum;
    private String code;

    public MemberVO() {
    }

    public MemberVO(String loginAcct, String userPswd, String email, String userName, String phoneNum, String code) {
        this.loginAcct = loginAcct;
        this.userPswd = userPswd;
        this.email = email;
        this.userName = userName;
        this.phoneNum = phoneNum;
        this.code = code;
    }

呼叫資料庫providerapi

@RequestMapping("/save/member/remote")
public ResultEntity<String> saveMember(@RequestBody MemberPO memberPO);

資料庫provider

資料庫儲存

Controller

@RequestMapping("/save/member/remote")
public ResultEntity<String> saveMember(@RequestBody MemberPO memberPO) {

    try {
        memberService.saveMember(memberPO);
        return ResultEntity.successWithoutData();
    } catch (Exception e) {
        if (e instanceof DuplicateKeyException) {
            return ResultEntity.failed(ConstantUtil.MESSAGE_LOGIN_ACCT_ALREADY_IN);
        }
        return ResultEntity.failed(e.getMessage());
    }
}

Service

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class, readOnly = false)
public void saveMember(MemberPO memberPO) {
    memberPOMapper.insertSelective(memberPO);
}

Mapper

int insertSelective(MemberPO record);

Sql

<insert id="insertSelective" parameterType="com.example.entity.po.MemberPO" >
  insert into t_member
  <trim prefix="(" suffix=")" suffixOverrides="," >
    <if test="id != null" >
      id,
    </if>
    <if test="loginAcct != null" >
      login_acct,
    </if>
    <if test="userPswd != null" >
      user_pswd,
    </if>
    <if test="userName != null" >
      user_name,
    </if>
    <if test="email != null" >
      email,
    </if>
    <if test="authStatus != null" >
      auth_status,
    </if>
    <if test="userType != null" >
      user_type,
    </if>
    <if test="realName != null" >
      real_name,
    </if>
    <if test="cardNum != null" >
      card_num,
    </if>
    <if test="acctType != null" >
      acct_type,
    </if>
  </trim>
  <trim prefix="values (" suffix=")" suffixOverrides="," >
    <if test="id != null" >
      #{id,jdbcType=INTEGER},
    </if>
    <if test="loginAcct != null" >
      #{loginAcct,jdbcType=VARCHAR},
    </if>
    <if test="userPswd != null" >
      #{userPswd,jdbcType=CHAR},
    </if>
    <if test="userName != null" >
      #{userName,jdbcType=VARCHAR},
    </if>
    <if test="email != null" >
      #{email,jdbcType=VARCHAR},
    </if>
    <if test="authStatus != null" >
      #{authStatus,jdbcType=INTEGER},
    </if>
    <if test="userType != null" >
      #{userType,jdbcType=INTEGER},
    </if>
    <if test="realName != null" >
      #{realName,jdbcType=VARCHAR},
    </if>
    <if test="cardNum != null" >
      #{cardNum,jdbcType=VARCHAR},
    </if>
    <if test="acctType != null" >
      #{acctType,jdbcType=INTEGER},
    </if>
  </trim>
</insert>

執行註冊

controller

@RequestMapping("/auth/do/member/register")
public String register(MemberVO memberVO, ModelMap modelMap) {
    // 1.獲取使用者輸入的手機號
    String phoneNum = memberVO.getPhoneNum();
    // 2.拼redis中儲存驗證碼的key
    String key = ConstantUtil.REDIS_CODE_PREFIX + phoneNum;
    // 3.從redis讀取key對應的value
    ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);
    // 4.查詢操作是否有效
    String result = resultEntity.getResult();
    if (ResultEntity.FAILED.equals(result)) {
        modelMap.addAttribute(ConstantUtil.ATTR_NANE_MESSAGE, resultEntity.getMessage());
        return "member-reg";
    }
    String redisCode = resultEntity.getData();
    if (redisCode == null) {
        modelMap.addAttribute(ConstantUtil.ATTR_NANE_MESSAGE, ConstantUtil.MESSAGE_CODE_NOT_EXISTS);
        return "member-reg";
    }
    // 5.如果能夠到value則比較表單的驗證碼和redis的驗證碼
    String formCode = memberVO.getCode();
    if (!Objects.equals(formCode, redisCode)) {
        modelMap.addAttribute(ConstantUtil.ATTR_NANE_MESSAGE, ConstantUtil.MESSAGE_CODE_INVALID);
        return "member-reg";
    }
    // 6.如果驗證碼一致,則從redis刪除
    redisRemoteService.removeRedisKeyRemote(key);
    // 7.執行密碼加密
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String userpswd = memberVO.getUserPswd();
    String encode = passwordEncoder.encode(userpswd);
    memberVO.setUserPswd(encode);
    // 8.執行儲存
    // 建立空的MemberPO物件
    MemberPO memberPO = new MemberPO();
    // 複製屬性
    BeanUtils.copyProperties(memberVO, memberPO);
    // 呼叫遠端方法
    ResultEntity<String> saveMemberResultEntity = mySQLRemoteService.saveMember(memberPO);
    if (ResultEntity.FAILED.equals(saveMemberResultEntity)) {
        modelMap.addAttribute(ConstantUtil.ATTR_NANE_MESSAGE, saveMemberResultEntity.getMessage());
        return "member-reg";
    }
    return "redirect:/auth/member/to/login/page";
}

一些問題

SpringBoot注入失敗的原因有哪些

SpringIOC找不到Bean物件

1、沒有開啟掃描的包

2、沒有注入Bean物件

3、沒有新增元件註解

4、方法沒有@Bean修飾

@FeignClients需要加入掃描哪些包才可以找到bean物件

mybatistrim prefix="(" suffix=")"

trim元素的主要功能是可以在自己包含的內容前加上某些字首,也可以在其後加上某些字尾,與之對應的屬性是prefixsuffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverridessuffixOverrides;正因為trim有這樣的功能,所以我們也可以非常簡單的利用trim來代替where元素的功能。

1.<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>

prefix:trim標籤內sql語句加上字首。

suffix:trim標籤內sql語句加上字尾。

suffixOverrides:指定去除多餘的字尾內容,如:suffixOverrides=",",去除trim標籤內sql語句多餘的字尾","

prefixOverrides:指定去除多餘的字首內容

suffixOverrides=","

執行的sql語句也許是這樣的:insert into cart (id,user_id,deal_id,) values(1,2,1,);顯然是錯誤的

指定之後語句就會變成insert into cart (id,user_id,deal_id) values(1,2,1);這樣就將去掉了。

字首同理。

獲取上述簡訊介面的appcode

阿里雲-》雲市場-API-》電子商務找到如下:

購買成功後