2023年12月10日 星期日

JSR-303 Bean Validation

 在以往Bean Validation通常會在service的function寫上好長一段判斷如下


//合法性校驗
  if (StringUtils.isBlank(dto.getName())) {
   throw new XueChengPlusException("課程名稱為空");
  }

  if (StringUtils.isBlank(dto.getMt())) {
   throw new XueChengPlusException("課程分類為空");
  }

  if (StringUtils.isBlank(dto.getSt())) {
   throw new XueChengPlusException("課程分類為空");
  }

  if (StringUtils.isBlank(dto.getGrade())) {
   throw new XueChengPlusException("課程等級為空");
  }

然而當欄位多起來的時候,code看起來就會變得冗長

且如果不同的function都要來一段這個,這些也有許多重複的程式碼其實也有改進空間

而在JavaEE6規範中就定義了參數校驗的規範

它就是JSR-303,它定義了Bean Validation,即對bean屬性進行校驗

SpringBoot提供了JSR-303的支持,它就是spring-boot-starter-validation,它的底層使用Hibernate Validator,Hibernate Validator是Bean Validation 的參考實現。

所以,我們準備在Controller層使用spring-boot-starter-validation完成對請求參數的基本合法性進行校驗。

以下的組合是可以讓不同的controller使用不同組的校驗文字
我們在專案中的exception包定出GlobalExceptionHandler和ValidationGroups



GlobalExceptionHandler

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    @ResponseBody
    @ExceptionHandler(XueChengPlusException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse customException(XueChengPlusException e) {
        log.error("【系統異常】{}",e.getErrMessage(),e);
        return new RestErrorResponse(e.getErrMessage());

    }

    @ResponseBody
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e) {

        log.error("【系統異常】{}",e.getMessage(),e);

        return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());

    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse methodArgumentNotValidException(MethodArgumentNotValidException e) {

        BindingResult bindingResult = e.getBindingResult();
        List msgList = new ArrayList<>();
        bindingResult.getFieldErrors().stream().forEach(item->{
            msgList.add(item.getDefaultMessage());
        });
        String msg = StringUtils.join(msgList, ",");
        log.error("【系統異常】{}",msg);
        return new RestErrorResponse(msg);

    }
}


ValidationGroups

public class ValidationGroups {
    public interface Insert{};
    public interface Update{};
    public interface Delete{};
}

目前將ValidationGroups分成新增, 更新, 刪除三個類別

在bean上設置的檢核訊息如下


@Data
@ApiModel(value="AddCourseDto", description="新增課程基本信息")
public class AddCourseDto {

 @NotEmpty(groups = {ValidationGroups.Insert.class},message = "新增課程名稱不能為空")
 @NotEmpty(groups = {ValidationGroups.Update.class},message = "修改課程名稱不能為空")
 @ApiModelProperty(value = "課程名稱", required = true)
 private String name;
 ...
 }

然後使用上, 我們在controller就可以這樣寫, 比方說我們此類為新增 就使用Insert @Validated({ValidationGroups.Insert.class})


    @ApiOperation("新增課程基礎信息")
    @PostMapping("/course")
    public CourseBaseInfoDto createCourseBase(@RequestBody @Validated({ValidationGroups.Insert.class}) AddCourseDto addCourseDto){
        //獲取到用戶所屬機構id
        Long companyId = 1232141425L;
        return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
    }

2023年12月1日 星期五

202312 思考人生方向日誌

轉軟體工程師 是201805

至今5年7個月, 工作約4年3個月

其中有

5個月進修android 5個月進修托福 1個月資料結構

5個月是工作轉換期(差不多轉換6次)

大致上被搞兩次, 一次加班太重, 兩次任務結束沒事做, 兩次被薪水更高機會挖走

真是超級波折, 以至於說, 忙著面試, 忙著適應 也是花了不少時間

以目前年薪來說102 勉勉強強及格, 也是算進了外商只是是駐點


本來練完英文, 想直接走國外工作

但是面試下來, 真正能開高的公司考的演算法考題及系統設計 高流量系統問答

這部分我還是有欠缺

還好在國泰時有機會讓我進修一下redis分布式鎖, 算是開啟了高併發的門

只是說還沒那麼熟練, 也還沒把學到的整理成系統就是, 打算等過幾個專案再來整理優良範例


今年過35了, 五子都沒半個影, 而面對現實的我, 其實壓力很大,

因為不小心還是把前女友留在身邊, 畢竟真的很愛她,

只是說如果要有小孩(後代)的話, 要另外找對象生了,


可能像別人就直接分手找下一個, 只是我捨不得

但是隨之而來, 在已有女友的情況下, 要再找一個女友

條件將會變得相當苛刻

並且可預期女生會需要我經濟上滿足她

每月若是3萬, 那除上0.05, 就是本金要600萬的年利率才足夠養小三

大概~是這樣想

然而, 工作這麼久, 其實有點疲乏, 白天上班有點累

也還是100公斤左右的體重, 是說體力比以前差不少

樣貌也是不太良好,

說實在, 真的壓力很大


還好債卷ETF有小賺, 算是站好了好買點

如果能賺個40萬出來, 對於我目前的困境幫助不少


看一下工作可能還是要找外商高流量工作好點

進修上安排, 可能平日都要有code練習(刷題)

就是說需要有make thing easier的安排


昨天看到說如果慾望足夠大, 方向也會變得相對紀律起來

如果已經得到滿足相對來說會比較躺(這部分要小心)


預計是說 目前先+1天運動

變成一, 三, 六 運動

二, 日刷題 六開局寫專案

四約人吃飯, 五六日玩電腦

上週六量97.5公斤, 希望體重78, 差不多一個月瘦3.3就行, 差不多一星期一公斤

先以目前的安排看看能不能維持一個月, 等後面再慢慢把其他安排加進來






2023年11月15日 星期三

crt, csr, key 初步認識SSL

在公司這邊有用到一個打api的驗證身分方式

在git-bash輸入

winpty openssl req -newkey rsa:2048 -keyout /c/path/client.key -out /c/path/client.csr -new

會產生兩個檔案

一個是csr, 另外一個檔案是key

另外他會要求

Verifying - Enter EPM pass phrase:

就是說, 要自己設一組密碼


這裡的驗證身分概念就是說, 我產生了一組Certificate Signing Request (CSR)

將這憑證給對方(可能上傳到某驗證網站), 然後由對方來產生另一組相對應crt


然後~我方再使用SSL身分, 附帶對方給的crt和我方的key file及pass phrase

對他方api進行呼叫

而在postman畫面如下

在setting中找到certificates的add and manage SSL on a per domain basis

點選add certificate











Host是他方網站

CRT是對方依照你上船的CSR相對應產生的身分憑證

KEY是你在產生CSR時, 同時產生的KEY

PFX(目前沒用到, 未知)

Passphrase是你在產生CSR和KEY file的時候輸入的密碼(很容易忘記, 要找地方抄下來)

基本上在這次工作經驗中用HOST, CRT, KEY, 及Passphrase就能完成身分驗證 

2023年11月10日 星期五

對應資料庫欄位技巧

可以在資料表上點選右鍵>Go to DDL











然後就會出現sql
















這樣就可以邊看sql編對應要寫入的欄位
為了方便點, 可以用螢幕擷取, 這樣隨時要對就開螢幕擷取框看, 很方便

2023年10月31日 星期二

cors

 

報錯問題如下

Access to XMLHttpRequest at 'http://localhost:63110/system/dictionary/all' from origin 'http://localhost:8601' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

從http://localhost:8601訪問http://localhost:63110/system/dictionary/all被CORS policy阻止,因為沒有Access-Control-Allow-Origin 頭信息。CORS全稱是 cross origin resource share 表示跨域資源共享。

出這個提示的原因是基於瀏覽器的同源策略,去判斷是否跨域請求,同源策略是瀏覽器的一種安全機制,從一個地址請求另一個地址,如果協議、主機、端口三者全部一致則不屬於跨域,否則有一個不一致就是跨域請求。

比如:

從http://localhost:8601  到   http://localhost:8602  由於端口不同,是跨域。

從http://192.168.101.10:8601  到   http://192.168.101.11:8601  由於主機不同,是跨域。

從http://192.168.101.10:8601  到   https://192.168.101.10:8601  由於協議不同,是跨域。


註意:服務器之間不存在跨域請求。

瀏覽器判斷是跨域請求會在請求頭上添加origin,表示這個請求來源哪裏。

比如:

GET / HTTP/1.1
Origin: http://localhost:8601


服務器收到請求判斷這個Origin是否允許跨域,如果允許則在響應頭中說明允許該來源的跨域請求,如下:
Access-Control-Allow-Originhttp://localhost:8601

如果允許任何域名來源的跨域請求,則響應如下:
Access-Control-Allow-Origin*

目前~簡易解法就是在所有的響應頭上加

 Access-Control-Allow-Origin*




import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @description: 跨域過慮器
 * @author: Ian Wang
 * @date: 2023/10/31 上午 10:38
 * @version: 1.0
 */
@Configuration
public class GlobalCorsConfig {
    /**
     * 允許跨域調用的過濾器
     */
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        //允許白名單域名進行跨域調用
        config.addAllowedOrigin("*");
        //允許跨越發送cookie
        config.setAllowCredentials(true);
        //放行全部原始頭信息
        config.addAllowedHeader("*");
        //允許所有請求方法跨域調用
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

2023年10月28日 星期六

使用idea運作vue專案

 首先先用idea打開一個vue專案






配置一下nodejs及npm路徑










在專案中找到package.json

這個相當於maven專案的pom文件, 用來管理前端的依賴

在上面點取Show npm Scripts





就能看到以下視窗









點serve右鍵 Run serve

(在run 之前須在專案根目錄打npm run install 不然會報

vue-cli-service不是内部或外部命令)

只要出現以下畫面說明啟動成功





就可以打開瀏覽器看一下~~

專案中node_modules本身相當於maven本地倉庫

裡面都是依賴的包, 刪除後 重新編譯, 他也會自動下載







2023年10月26日 星期四

使用httpclient

在idea可下載工具中有httpclient

其功用很像是postman或是swagger

他的功用上, 一方面能保存測試數據, 另外一方面又比postman吃的資源少

同時因其在idea裡面, 使用上還算方便

下列簡略介紹

可以創一個資料夾專門放這些測試

裡面命名用.http結尾, 內容為以下

需要有content type, 然後~格一行可以寫requestbody

點選綠色箭頭就可以run

另外一部分可以設置環境變數, 像{{content_host}}

然後創建一個env檔案ex http-client.env.json

然後內容

{
"dev": {
"access_token": "",
"gateway_host": "localhost:63010",
"content_host": "localhost:63040",
"system_host": "localhost:63110",
"media_host": "localhost:63050",
"search_host": "localhost:63080",
"auth_host": "localhost:63070",
"checkcode_host": "localhost:63075",
"learning_host": "localhost:63020"
}
}
這樣就可以選run with 'dev' environment








2023年10月24日 星期二

從資料庫產生entity&mapper

mybatis-plus的generatort生成工具 
生成 PO類、Mapper接口、Mapper的xml文件 

來源
 https://github.com/baomidou/generator 

將xuecheng-plus-generator.zip解壓後複製到專案的根目錄 如下














在專案中找到pom檔案, 點選右鍵add as maven project
才能使用















在這包中找到ContentCodeGenerator類別














TABLE_NAMES後面可以指定要生成的數據表











資料庫連線, 則是在下面程式碼中做配置








然後就可以run這個application, 產生結果會在和generator同層的包 content中
裡面包含controller, mapper, model 還有service







2023年10月17日 星期二

全局date time

 當回應的日期格式中有T還有毫秒的時候














或許我們會思考如何改它的格式

有一個方法, 可以做全局的統一



@Configuration
public class LocalDateTimeConfig {

    /*
     * 序列化内容
     *   LocalDateTime -> String
     * 服务端返回给客户端内容
     * */
    @Bean
    public LocalDateTimeSerializer localDateTimeSerializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /*
     * 反序列化内容
     *   String -> LocalDateTime
     * 客户端传入服务端数据
     * */
    @Bean
    public LocalDateTimeDeserializer localDateTimeDeserializer() {
        return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }


    // 配置
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            builder.serializerByType(LocalDateTime.class, localDateTimeSerializer());
            builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
        };
    }

}

透過上面的方式, 就能統一格式

結果:

2023年8月11日 星期五

linux note-2

分辨文件 文件夾

ls -l

其中d開頭為文件夾, -開頭為文件

cat 支持看文件

但是當文件太長的時候, 變得難以閱讀

ex

cat /etc/services


而 翻頁查看 可以方便看長文件

ex

 more /etc/services

翻頁 按 空白鍵

退出 按 q


小結

1. touch命令

用于创建一个新的文件

语法:touch linux 路徑

参数必填,表示要创建的文件的路径,相对、绝对、特殊路径符都可以使用

2. cat命令

用于查看文件内容

语法:cat linux 路徑

参数必填,表示要查看的文件的路径,相对、绝对、特殊路径符都可以使用

3. more命令

用于查看文件内容,可翻页查看

语法:more linux路徑

参数必填,表示要查看的文件的路径,相对、绝对、特殊路径符都可以使用

使用空格进行翻页,使用q退出查看


2023年6月29日 星期四

linux note-1

計算機 由硬件和軟件組成, 而操作系統就是軟件

連線查詢
ifconifig




然後打開finalshell



輸入連線資訊




ls 
顯示目錄

cd
change directory
回到home

cd/
回到根目錄

pwd
print work directory
查看當前工作目錄

cd ..
切換到上一層

cd ../..
切換到上上層

cd ~
切換到home == cd home

cd ~/Desktop
進到home下的Desktop目錄

範例>>>>>>>>>>>>>>>>>>
当前工作目录内有一个test文件夹,文件夹内有一个文件hello.txt,请描述文件的相对路径
test/hello.txt
在当前工作目录的上级目录有一个test文件夹,文件夹内有一个文件hello.txt,请描述文件的相对路径
../test/hello.txt
在HOME目录内有一个test文件夹,文件夹内有一个文件hello.txt,请描述文件的路径,需要使用符号~
~/test/hello.txt

mkdir [-p] linux路徑
make directory

-p 自動創建不存在父目錄, 是連續層級父目錄

一次創建多個層級時, 是會報錯的
需要加上-p
另外
ctrl + L 可以清空頻目

注意:创建文件夹需要修改权限,请确保操作均在HOME目录内,不要在HOME外操作
涉及到权限问题,HOME外无法成功
后续我们会讲解权限管控的知识







[leetcode] [KMP] KMP

ABCDABD... ABCDABF... 簡單的說, 傳統解兩字串匹配部分 可能會來個雙迴圈, 哀個比對, 當不匹配的時候, 會將下方列再後移1位 然後不匹配再後移 然而 如果像上放已經有4個屬於匹配的字串, 她就應該直接往後移四位來匹配, 而不是只移動1位 隱藏的思維是, 當...