成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[Spring cloud 一步步實(shí)現(xiàn)廣告系統(tǒng)] 6. Service實(shí)現(xiàn)&Zuul配置&a

孫淑建 / 1302人閱讀

摘要:所以,沒(méi)必要過(guò)分糾結(jié)這種信息,咬文嚼字有時(shí)候反而會(huì)適得其反。若初通用錯(cuò)誤信息異常類請(qǐng)求參數(shù)異常用戶已存在用戶不存在在下面創(chuàng)建一個(gè)工具類用來(lái)對(duì)用戶進(jìn)行加密來(lái)獲取信息。工具類若初加密參考創(chuàng)建用戶的實(shí)現(xiàn),依次實(shí)現(xiàn)其他表操作。

DAO層設(shè)計(jì)實(shí)現(xiàn)

這里我們使用Spring DATA JPA來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作,當(dāng)然大家也可以使用Mybatis,都是一樣的,我們依然以用戶表操作為例:

/**
 * AdUserRepository for 用戶數(shù)據(jù)庫(kù)操作接口
 * 繼承自JpaRepository,第一個(gè)參數(shù)AdUser代表當(dāng)前要操作的實(shí)體類的class定義,第二個(gè)參數(shù)Long表示該類的主鍵類型
 *
 * @author Isaac.Zhang
 */

public interface AdUserRepository extends JpaRepository { 
    /**
     * 根據(jù)用戶名稱獲取用戶
     *
     * @param username 名稱
     * @return 用戶對(duì)象
     */
    AdUser findByUserName(String username);

    List findAllByUserName(String userName);
}

JPARepository 的默認(rèn)實(shí)現(xiàn)方法,如果我們只是繼承了JpaRepository而沒(méi)有實(shí)現(xiàn)具體的操作方法,我們也是可以通過(guò)使用它的默認(rèn)方法來(lái)做CRUD操作的,如下:

功能Service實(shí)現(xiàn)

創(chuàng)建service package,依然以用戶操作為例,創(chuàng)建com.sxzhongf.ad.service.IUserServicecom.sxzhongf.ad.service.impl.UserServiceImpl,UserServiceImpl實(shí)現(xiàn)了IUserService。

創(chuàng)建 IUserService 接口

/**
 * IUserService for 用戶service
 *
 * @author Isaac.Zhang | 若初
 */
public interface IUserService {
    /**
     * 創(chuàng)建用戶接口
     *
     * @param userRequestVO {@link UserRequestVO}
     * @return {@link UserResponseVO}
     * @throws AdException 錯(cuò)誤
     */
    UserResponseVO createUser(UserRequestVO userRequestVO) throws AdException;

    List findAllByUserName(String userName);
}

使用IUserService接口

/**
 * UserServiceImpl for 用戶service
 *
 * @author Isaac.Zhang | 若初
 */
@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    private final AdUserRepository userRepository;

    @Autowired
    public UserServiceImpl(AdUserRepository userRepository) {
        this.userRepository = userRepository;
    }

    /**
     * 創(chuàng)建用戶
     *
     * @param userRequestVO {@link UserRequestVO}
     * @return result {@link UserResponseVO}
     */
    @Override
    @Transactional
    public UserResponseVO createUser(UserRequestVO userRequestVO) throws AdException {
        if (!userRequestVO.validate()) {
              log.error("Request params error: {}", userRequestVO);
            throw new AdException(Constants.ErrorMessage.REQUEST_PARAM_ERROR);
        }
        //查重
        AdUser existUser = userRepository.findByUserName(userRequestVO.getUserName());
        if (existUser != null) {
            log.error("{} user is not exist.", userRequestVO.getUserName());
            throw new AdException(Constants.ErrorMessage.USER_EXIST);
        }
        AdUser user = userRepository.save(new AdUser(userRequestVO.getUserName(), CommonUtils.md5(userRequestVO.getUserName())));
        log.info("current user is : {}", user);
        return new UserResponseVO(user.getUserId(), user.getUserName(), user.getToken(),
                user.getCreateTime(), user.getUpdateTime());
    }

    @Override
    public List findAllByUserName(String userName) {
        return userRepository.findAllByUserName(userName);
    }
}

創(chuàng)建數(shù)據(jù)傳輸對(duì)象(dto/vo)

其實(shí)好多人在這里都會(huì)特別郁悶,搞不清楚這些命名有什么區(qū)別,個(gè)人建議是大家不用糾結(jié),dto(data transfer object),就是表示我們?cè)诟鱾€(gè)層傳遞的對(duì)象,vo在展示層操作的對(duì)象。但是這個(gè)只是個(gè)命名,它的本質(zhì)就是一個(gè)object, 你傳遞到DAO層可以嗎?當(dāng)然可以,你傳多帶帶字段都是可以的。所以,沒(méi)必要過(guò)分糾結(jié)這種信息,咬文嚼字有時(shí)候反而會(huì)適得其反。

/**
 * UserRequestVO for 創(chuàng)建用戶請(qǐng)求對(duì)象VO
 *
 * @author Isaac.Zhang | 若初
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRequestVO {
    private String userName;
    public boolean validate() {
        return !StringUtils.isEmpty(userName);
    }
}

---
  
/**
 * UserResponseVO for 用戶響應(yīng)VO
 *
 * @author Isaac.Zhang | 若初
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserResponseVO {
    private Long userId;
    private String userName;
    private String token;
    private Date createTime;
    private Date updateTime;
}

因?yàn)閳?bào)錯(cuò)信息有可能是相同的,那我們抽取一個(gè)常量類來(lái)封裝。

/**
 * Constants for TODO
 *
 * @author Isaac.Zhang | 若初
 */
public class Constants {
    /**
     * 通用錯(cuò)誤信息異常類
     */
    public static class ErrorMessage {
        public static final String REQUEST_PARAM_ERROR = "請(qǐng)求參數(shù)異常";
        public static final String USER_EXIST = "用戶已存在";
        public static final String USER_NOT_EXIST = "用戶不存在";
    }
}

在Common Project 下面創(chuàng)建一個(gè)工具類com.sxzhongf.ad.common.utils.CommonUtils,用來(lái)對(duì)用戶username進(jìn)行md5加密來(lái)獲取token信息。

/**
 * CommonUtils for 工具類
 *
 * @author Isaac.Zhang | 若初
 */
@Slf4j
public class CommonUtils {
    /**
     * md5 加密
     */
    public static String md5(String value) {
        return DigestUtils.md5Hex(value).toUpperCase();
    }
}

參考創(chuàng)建用戶的實(shí)現(xiàn),依次實(shí)現(xiàn)其他表操作。

Controller實(shí)現(xiàn)

依然以用戶功能實(shí)現(xiàn)為例:

/**
 * UserController for 用戶controller
 *
 * @author Isaac.Zhang | 若初
 */
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userService;

    @PostMapping(path = "/create")
    public UserResponseVO createUser(@RequestBody UserRequestVO requestVO) throws AdException {
        log.info("ad-sponsor: createUser -> {}", JSON.toJSONString(requestVO));
        return userService.createUser(requestVO);
    }

    @GetMapping(path = "/get")
    public CommonResponse getUserList(@Param(value = "username") String username) throws AdException {
        log.info("ad-sponsor: getUserList -> {}", JSON.toJSONString(username));
        return new CommonResponse(userService.findAllByUserName(username));
    }
}
在網(wǎng)關(guān)中配置廣告投放系統(tǒng)

我們?cè)谕斗畔到y(tǒng)的配置中,配置了server.servlet.context-path:/ad-sponsor這么一個(gè)路徑,意味著所有請(qǐng)求當(dāng)前系統(tǒng)的路徑都需要帶有ad-sponsor, 例如:http://xxx/ad-sponsor/user/get?username=yyy,這是網(wǎng)關(guān)請(qǐng)求所必需的。根據(jù)上述,我們?cè)诰W(wǎng)關(guān)服務(wù)中配置我們當(dāng)前的投放系統(tǒng):

spring:
  application:
    name: ad-gateway-zuul
server:
  port: 1111
eureka:
  client:
    service-url:
      defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/
  instance:
    hostname: ad-gateway-zuul
##############################################
# 以下為重要信息
zuul:
  ignored-services: "*" # 過(guò)濾所有請(qǐng)求,除了下面routes中聲明過(guò)的服務(wù)
  # 配置網(wǎng)關(guān)路由規(guī)則
  routes:
    sponsor: #在路由中自定義服務(wù)路由名稱
      path: /ad-sponsor/**
      serviceId: mscx-ad-sponsor #微服務(wù)name
      strip-prefix: false
    search: #在路由中自定義服務(wù)路由名稱
      path: /ad-search/**
      serviceId: mscx-ad-search #微服務(wù)name
      strip-prefix: false
  prefix: /gateway/api
  strip-prefix: false #不對(duì) prefix: /gateway/api 設(shè)置的路徑進(jìn)行截取,默認(rèn)轉(zhuǎn)發(fā)會(huì)截取掉配置的前綴
Test

直接訪問(wèn)投放系統(tǒng)

調(diào)用curl -G http://localhost:7000/ad-sponsor/user/get?username=Isaac%20Zhang,返回結(jié)果:

{
  code: 0,  // 統(tǒng)一成功標(biāo)示
  message: "success", // 統(tǒng)一處理結(jié)果message
  data: [  // 具體的對(duì)象信息
    {
      userId: 10,
      userName: "Isaac Zhang",
      token: "2D3ABB6F2434109A105170FB21D00453",
      userStatus: 1,
      createTime: 1561118873000,
      updateTime: 1561118873000
    }
  ]
}

通過(guò)網(wǎng)關(guān)調(diào)用

因?yàn)槲以诰W(wǎng)關(guān)配置中加了前綴prefix: /gateway/api,因此,我們?cè)L問(wèn)的時(shí)候需要添加上這個(gè)前綴信息,否則會(huì)報(bào)404錯(cuò)誤。

curl -G http://localhost:1111/gateway/api/ad-sponsor/user/get?username=Isaac%20Zhang,我們發(fā)現(xiàn)結(jié)果并沒(méi)有按照我們想象的展示出來(lái)。

bogon:~ zhangpan$ http://localhost:1111/gateway/api/ad-sponsor/user/get?username=Isaac%20Zhang
-bash: http://localhost:1111/gateway/api/ad-sponsor/user/get?username=Isaac%20Zhang: No such file or directory

為什么呢?我們來(lái)查看一下日志:

2019-07-27 20:44:19.093  INFO 4766 --- [nio-1111-exec-4] c.s.a.g.filter.ValidateTokenFilter       : GET request to http://localhost:1111/gateway/api/ad-sponsor/user/get
2019-07-27 20:44:19.093  WARN 4766 --- [nio-1111-exec-4] c.s.a.g.filter.ValidateTokenFilter       : access token is empty
2019-07-27 20:44:19.098  INFO 4766 --- [nio-1111-exec-4] c.s.ad.gateway.filter.AccessLogFilter    : Request "/gateway/api/ad-sponsor/user/get" spent : 0 seconds.
2019-07-27 20:48:37.801  INFO 4766 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration

我們可以清晰的看到,ValidateTokenFilter : access token is empty,為什么會(huì)有這么一個(gè)報(bào)錯(cuò)呢?那是因?yàn)槲以谂渲镁W(wǎng)關(guān)的時(shí)候,添加了一次攔截:

/**

*

@author Isaac.Zhang

*/
@Slf4j
@Component
public class ValidateTokenFilter extends ZuulFilter {
...

  @Override
  public Object run() throws ZuulException {
      RequestContext ctx = RequestContext.getCurrentContext();
      HttpServletRequest request = ctx.getRequest();
      log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));

      Object accessToken = request.getHeader("accessToken"); //.getParameter("accessToken");
      if (accessToken == null) {
          log.warn("access token is empty");
          ctx.setSendZuulResponse(false);
          ctx.setResponseStatusCode(401);

// ctx.setResponseBody(body)對(duì)返回body內(nèi)容進(jìn)行編輯

          return null;
      }
      log.info("access token ok");
      return null;
  }

}

觀察代碼我們發(fā)現(xiàn),會(huì)從`RequestHeader`中獲取`accessToken`參數(shù),我們沒(méi)有提供,當(dāng)然就會(huì)報(bào)錯(cuò)了呀。接下來(lái),我們提供上該參數(shù)再試:

bogon:~ zhangpan$ curl -H "accessToken:true" http://localhost:1111/gateway/api/ad-sponsor/user/get?username=Isaac%20Zhang
---返回
{"code":0,"message":"success","data":[{"userId":10,"userName":"Isaac Zhang","token":"2D3ABB6F2434109A105170FB21D00453","userStatus":1,"createTime":1561118873000,"updateTime":1561118873000}]}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75645.html

相關(guān)文章

  • [Spring cloud 步步實(shí)現(xiàn)廣告系統(tǒng)] 3. 網(wǎng)關(guān)路由

    摘要:獲取當(dāng)前請(qǐng)求的請(qǐng)求上下文記錄請(qǐng)求進(jìn)入時(shí)間需要最后一個(gè)執(zhí)行的后續(xù)更新做一個(gè)好人。 Zuul(Router and Filter) WIKI: 傳送門(mén) showImg(https://i.loli.net/2019/07/24/5d38183f1dff763558.png); 作用 認(rèn)證,鑒權(quán)(Authentication/Security) 預(yù)判(Insights) 壓力測(cè)試(Stre...

    miguel.jiang 評(píng)論0 收藏0
  • [Spring cloud 步步實(shí)現(xiàn)廣告系統(tǒng)] 7. 中期總結(jié)回顧

    摘要:在前面的過(guò)程中,我們創(chuàng)建了個(gè)服務(wù)發(fā)現(xiàn)我們使用作為服務(wù)發(fā)現(xiàn)組件,學(xué)習(xí)了的使用。加依賴加注解改配置使用項(xiàng)目三部曲,我們可以快速添加一個(gè)新組件,并正常使用這個(gè)我沒(méi)有在項(xiàng)目中實(shí)現(xiàn),但是大家可以和一樣,三部曲搞定。 在前面的過(guò)程中,我們創(chuàng)建了4個(gè)project: 服務(wù)發(fā)現(xiàn) 我們使用Eureka 作為服務(wù)發(fā)現(xiàn)組件,學(xué)習(xí)了Eureka Server,Eureka Client的使用。 Eureka...

    cnsworder 評(píng)論0 收藏0
  • [Spring cloud 步步實(shí)現(xiàn)廣告系統(tǒng)] 8. 檢索系統(tǒng)配置&依賴

    摘要:工作流程項(xiàng)目依賴監(jiān)控面板引入服務(wù)調(diào)用的組件依賴引入服務(wù)消費(fèi)者的依賴數(shù)據(jù)庫(kù)鏈接依賴工具類集合類操作日志監(jiān)聽(tīng)解析開(kāi)源工具類庫(kù)中的配置相關(guān)依賴圖片壓縮 工作流程 showImg(https://i.loli.net/2019/07/29/5d3ee1829df4d57461.png); 項(xiàng)目依賴 org.springframewo...

    dailybird 評(píng)論0 收藏0
  • [Spring cloud 步步實(shí)現(xiàn)廣告系統(tǒng)] 9. 主類和配置文件

    摘要:搜索系統(tǒng)啟動(dòng)主類廣告搜索服務(wù)啟動(dòng)類若初啟動(dòng)客戶端,為了訪問(wèn)其他微服務(wù)開(kāi)啟服務(wù)發(fā)現(xiàn)組件,在這里等同于開(kāi)啟斷路器斷路器開(kāi)啟監(jiān)控配置文件請(qǐng)求的根路徑請(qǐng)求前綴,在的之前,需要執(zhí)行時(shí)是否打印語(yǔ)句,方便調(diào)試控制是否在懶加載時(shí),有可能會(huì) 搜索系統(tǒng)啟動(dòng)主類 /** * AdSearchApplication for 廣告搜索服務(wù)啟動(dòng)類 * * @author Isaac.Zhang | 若初 ...

    junbaor 評(píng)論0 收藏0
  • 微服務(wù)網(wǎng)關(guān)方案調(diào)研

    摘要:綜述經(jīng)調(diào)研,使用解決方案的占多數(shù),已經(jīng)能滿足絕大多數(shù)公司需求。但除了一些超級(jí)公司外,比如阿里,京東,他們是自己擼的一套網(wǎng)關(guān)。 綜述 經(jīng)調(diào)研,使用Spring Cloud Zuul解決方案的占多數(shù),已經(jīng)能滿足絕大多數(shù)公司需求。但除了一些超級(jí)公司外,比如阿里,京東,他們是自己擼的一套網(wǎng)關(guān)。此外,點(diǎn)評(píng)直接采用的nginx負(fù)載均衡前置網(wǎng)關(guān),而沒(méi)用第七層網(wǎng)關(guān),原因據(jù)說(shuō)是七層網(wǎng)關(guān)會(huì)影響性能,但由于...

    Y3G 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<