這是使用Spring boot 建立資料庫連線遇到的問題
解決方法
在後方加入?serverTimezone=UTC
如果要解決中文亂碼問題
也可以加入?useUnicode=true&characterEncoding=UTF-8
合起來可以 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
這是使用Spring boot 建立資料庫連線遇到的問題
解決方法
在後方加入?serverTimezone=UTC
如果要解決中文亂碼問題
也可以加入?useUnicode=true&characterEncoding=UTF-8
合起來可以 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
曾經, 我以為這個目標可能還要兩三年
沒想到有公司如此欣賞我
願意給我這樣的價格
雖然, 我達成了目標, 讓我將這段時間的努力, 寫成文章記錄
一個商學院的學生, 轉職成為工程師的故事
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
背景, 我大學念元智國企, 研究所念銘傳財金
其實並沒有說多強悍
只是研究所期間寫點交易&統計程式
多益拿過890金色證照, 業餘圍棋5段, 當過合唱教學, 小提琴家教
也是在有興趣的領域, 認真專注, 也小有收穫
當初出社會跌跌撞撞並沒有銀行收我, 直到一家會計師事務所
我看這地方有點品質, 是做外商的, 想說, 喜歡投資的這部分
有機會進來加強一下公司會計帳務的知識,沒想到~~
會計太弱了, 只好去做薪資組, 當時我一連管了10多家薪資報表
自以為很厲害, 但是看著各家員工的薪資與自己薪資的差距, 我急了
於是我問當初的部門經理:"如果我在這家公司工作8年10年, 有沒有機會領到8-10萬?"
經理斬釘截鐵地說: "絕對沒有可能"
於是我當下就決定要離職
"這個行業沒機會, 但是其他的有"
看著這些外商給的薪資, 我認為自己並沒有比較差,
只是還找不到哪一種類工作能讓我好好發揮
我到底還能做什麼?
我自己遇到問題的情況
是在接手的專案中
多國語言中有message.properties檔案的問題
內容的字發生問題如下
\u4e2d\u6587\u5b57
解決方式如下
必須去idea中的 file>Settings
考題: 給定兩個字串, 寫一個方法判斷一個是否是另一個的變位字
思維:造一個方法
1 先比較其長度是否相等
2 比較兩個值做順序排序, 內容是否會相等
順序排序:
a 產生一個字元char陣列
b使用Arrays.sort
c產生新的字串
public static void main(String[]args){
System.out.println(permutation("see","ese"));
}
static String sort(String s){
char[]content = s.toCharArray();
java.util.Arrays.sort(content);
return new String(content);
}
static boolean permutation(String s, String t){
if(s.length()!=t.length()){
return false;
}
return sort(s).equals(sort(t));
}
考題: 實作一個演算法來判斷一個字串中的字元是否不重複. 如果不能使用其他資料結構怎麼辦?
思維:假設字元有128個, 每一個都有特殊的數字, 因此~
1 造一個布林陣列
2 跑迴圈, 當遇到新的字元數字, 布林陣列[數字] 改為true
3 下一次再來, 如果發現其布林陣列[數字]為true , 代表該字元已經出現過了,
然後整個function就要回傳false
public static void main(String[] args) {
System.out.println(isUniqueChars("abbs"));
}
static boolean isUniqueChars(String str) {
if(str.length() > 128) return false;
boolean[]char_set = new boolean[128];
for(int i =0 ; i < str.length() ; i++) {
int val =str.charAt(i);
System.out.println(val);
if(char_set[val]) {
return false;
}
char_set[val]=true;
}
return true;
}
引入靜態頁面的時候
我們原本可能會使用
<link rel="stylesheet" href="../../static/css/me.css">
這個語法在模板templates(有引入thymeleaf)下, 並不能讀取到
因此~需要改為
<link rel="stylesheet" href="../../static/css/me.css" th:href="@{/css/me.css}">
用th:href="@{}"來引入資源
然後重新build再刷新頁面就沒問題了
---------------------------------------------------------------------------------------
使用fragment
1 首先產生一個html檔案命名為_fragments
2 然後我們將大部分頁面上會重複的程式碼複製到這頁面
ex
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客詳情</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
<link rel="stylesheet" href="../static/css/typo.css">
<link rel="stylesheet" href="../static/css/animate.css">
<link rel="stylesheet" href="../static/lib/prism/prism.css">
<link rel="stylesheet" href="../static/lib/tocbot/tocbot.css">
<link rel="stylesheet" href="../static/css/me.css">
</head>
3 將引入方式修改為th:href="@{}"
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
<link rel="stylesheet" href="../static/css/typo.css" th:href="@{css/typo.css}">
<link rel="stylesheet" href="../static/css/animate.css" th:href="@{css/animate.css}">
<link rel="stylesheet" href="../static/lib/prism/prism.css" th:href="@{/lib/prism/prism.css}">
<link rel="stylesheet" href="../static/lib/tocbot/tocbot.css" th:href="@{/lib/tocbot/tocbot.css}">
<link rel="stylesheet" href="../static/css/me.css" th:href="@{/css/me.css}">
4 將重複的片段掛上fragment
<head th:fragment="head(title)">
5 如果遇到每個頁面有共通元素, 但是內容不一樣,
例如 <title>博客詳情</title>
這時候我們就要使用傳參數的方式(注意取參數要用$)
<head th:fragment="head(title)">
<title th:replace="${title}">博客詳情</title>
</head>這樣來做搭配
6 而在要引入的頁面(比方說index.html)
我們可以這樣做, 這樣就是將title裡面的參數傳遞過去
<head th:replace="_fragments :: head(~{::title})">
完整的程式碼:
_fragments.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head th:fragment="head(title)">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title th:replace="${title}">博客詳情</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
<link rel="stylesheet" href="../static/css/typo.css" th:href="@{css/typo.css}">
<link rel="stylesheet" href="../static/css/animate.css" th:href="@{css/animate.css}">
<link rel="stylesheet" href="../static/lib/prism/prism.css" th:href="@{/lib/prism/prism.css}">
<link rel="stylesheet" href="../static/lib/tocbot/tocbot.css" th:href="@{/lib/tocbot/tocbot.css}">
<link rel="stylesheet" href="../static/css/me.css" th:href="@{/css/me.css}">
</head>
<body>
</body>
</html>
index.html 的header
<head th:replace="_fragments :: head(~{::title})">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
<link rel="stylesheet" href="../static/css/me.css" >
</head>
關於橫切面AOP的思維
個人的領會是, 在程式進行的流程為一個直向的流層, 但是, 如果要在其中幾個物件被使用的時候,都插入一段程式碼, 這種的思想就是橫切面設計,
具體的範例, 是一種鑲嵌, 縫合程式碼的思維, 比方說在每一次從某些controller的時候都警示該功能已經被呼叫, 就是都額外run一段程式碼, 如果說要在每個controller上面加上這段, 就是一個麻煩的事, 如果我們在後面才設計出要被加入的這段程式碼, 那還不如能用縫合的, 將其呼叫的時機設定好, 然後不用每個controller都重新鑲入該程式碼, 那這下面會有些關鍵字的思維可以釐清
1 切面Aspect
切面是一個模塊關注點的模塊化, 他由切入點PointCut和通知Advice組成
@Aspect
@Component
public class LogAspect {
}
2 目標Target
將要被縫合的類別, 比方說, 我們就設計了一個controller, 等下測試縫合程式碼的執行順序
@Controller
public class IndexController {
@GetMapping("/{id}/{name}")
public String index(@PathVariable Integer id, @PathVariable String name){
System.out.println("~~~~~~~~~~~~index~~~~~~~~~~");
return "index";
}
}
3 連接點JoinPoint
被視為切入連接點, 是下列範例中的log()方法
@Before("log()")
public void doBefore(JoinPoint joinPoint){logger.info("~~~~~~~Before~~~~~~~");}
4 切入點PointCut
而切入點則是下面括號中指定execution中的東西,* 是指說返回任何東西
com.lrm.web.*.*(..)是AOP要切入的對象, web後面*表示任何類,第二個*表示任何方法
而(..)表示任何參數, 當然也可以使用web.IndexController 這樣就只有這個Controller會被
橫切插入程式
@Pointcut("execution(* com.lrm.web.*.*(..))")
public void log(){
}
5 通知Advice
有不同被通知的種類, 比方說Before, After,
@Before("log()")
public void doBefore(JoinPoint joinPoint){logger.info("~~~~~~~Before~~~~~~~");}
@After("log()")
public void doAfter(){
logger.info("~~~~~~~After~~~~~~~");
}
6 織入Weaving
將切面Aspect與對象Target連接起來, 織入可以在類別加載的的時候完成, 也可以在編譯, 或是運行的時候完成...如果是編譯時完成就是靜態代理, 如果在運行時完成就是動態代理
--------------------------------------------------------------------------------------
以下是一個完整的程式碼
會設計一個內部類別, 然後將其Url, ip, 目標的物件名稱及參數都印出來
package com.lrm.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Aspect
@Component
public class LogAspect {
private final Logger logger= LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(* com.lrm.web.*.*(..))")
public void log(){
}
@Before("log()")
public void doBefore(JoinPoint joinPoint){
logger.info("~~~~~~~before~~~~~~~");
ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request=attributes.getRequest();
String url =request.getRequestURL().toString();
String ip=request.getRemoteAddr();
String classMethod=joinPoint.getSignature().getDeclaringTypeName() + "." +joinPoint.getSignature().getName();
Object[] args= joinPoint.getArgs();
RequestLog requestLog= new RequestLog(url,ip,classMethod,args);
logger.info("Request : {}",requestLog);
}
@After("log()")
public void doAfter(){
logger.info("~~~~~~~After~~~~~~~");
}
@AfterReturning(returning = "result" , pointcut = "log()")
public void doAfterReturn(Object result){
logger.info("Result: {}",result);
}
private class RequestLog{
private String url;
private String ip;
private String classMethod;
private Object[] args;
public RequestLog(String url, String ip, String classMethod, Object[] args) {
this.url = url;
this.ip = ip;
this.classMethod = classMethod;
this.args = args;
}
@Override
public String toString() {
return "RequestLog{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", classMethod='" + classMethod + '\'' +
", args=" + Arrays.toString(args) +
'}';
}
}
}
再搭配上前面的IndexController, 開啟然後輸入 http://localhost:8081/1/hat
後面兩個參數是先隨意給的, 以下是結果的截圖
參考網址:
https://zhuanlan.zhihu.com/p/60842627
https://matthung0807.blogspot.com/2018/02/spring-aop.html
AI 時代的軟體工程:從「代碼寫手」到「系統指揮官」的轉型之路 2026 年,軟體工程正經歷自編譯器發明以來最大的範式轉移。AI 不再只是 IDE 側邊欄的輔助工具,而是進化為具備自主性的 Agent(代理人) ,這場變革正重新定義「工程師」的核心價值。 一、 現狀:AI 普...