天,有漁老師去現(xiàn)場為一位朋友解決一個網(wǎng)站注冊驗證的問題。問題是這樣的:在朋友的網(wǎng)站用郵箱注冊后,系統(tǒng)會發(fā)一封郵件到郵箱,然后點擊鏈接設(shè)置賬號的初始化密碼。如下圖所示:
但我點擊這個鏈接后,wordpress一直提示invalid key,也就是說key錯誤。因為是wordpress框架,從url的路由看,我就打開wp-login.php,然后查看其中的action rp。我直觀感覺,應(yīng)該是get url中的key跟數(shù)據(jù)庫中的key值不相等導致的。所以,想進入系統(tǒng)的mysql一查究竟,但遺憾的是竟然沒有mysql權(quán)限,我也不知道他的網(wǎng)站是讓誰做的,估計是個外包吧。因為朋友是不懂技術(shù)的,很多事情問他也是一問三不知。沒辦法,哪就自己悶頭搞吧。
外事不決問google,內(nèi)事不決問baidu。我習慣性地打開baidu,輸入:wordpress新用戶注冊 key無效。發(fā)現(xiàn)碰到類似問題的同行也不少,且看他們是如何解決的?他們的建議是:
編輯wp-includes文件夾中的pluggable.php文件,把變量$message里的>符合去掉。我照做了,發(fā)現(xiàn)還是不行的哦。所以,網(wǎng)上的東西,很多都得自己再實踐下,否則是要被坑的。但到這一步,我更加確信是key的值出問題了。然后我又仔細看了下郵件發(fā)送過來的鏈接,發(fā)現(xiàn)這個鏈接有個問題。
這個鏈接里的&是&被轉(zhuǎn)義后的值。那么,我在瀏覽器里輸入時把&替換成&會怎樣呢?發(fā)現(xiàn)竟然OK了,這時密碼重置成功了。這樣,問題就好辦了,理論上,我只要修改pluggable.php,把&替換成&就可以了。$message的變量賦值如下:
$message .= ‘<‘ . network_site_url(“wp-login.php?action=rp&key=$key&login=” . rawurlencode($user->user_login), ‘login’) . “>\r\n\r\n”;
但問題是,我用htmlspecialchars_decode($message)處理也不行,用str_replace("&","&",$message)處理也不行。也就是說,這個&替換不成&。
我再看這$message變量,rp后面的&怎么沒被轉(zhuǎn)義,而$key后面的&卻被轉(zhuǎn)義了。所以,到這一步,我就懷疑是不是語句的順序有問題?然后,我就把&key=$key放到($user->user_login)后面。然后,根據(jù)前面baidu的一些意見,順便把<和>符合也去掉。這樣,修改后的message如下:
$message .= network_site_url(“wp-login.php?action=rp&login=” . rawurlencode($user->user_login)."&key=$key", ‘login’) . “\r\n\r\n”;
問題就這樣解決了。
總結(jié):1,出現(xiàn)問題,問baidu一般都能找到一些建議。但這些建議不一定完全正確,自己還得根據(jù)實際情況修改。2,html的一些特殊符號,在存數(shù)據(jù)庫之前需要被轉(zhuǎn)義,在取出數(shù)據(jù)庫后,需要被轉(zhuǎn)換回來,這也是一個很重要的知識點。
mybatis 的 xml 文件里寫的 sql 語句實際用的是一門叫做 OGNL 的表達式語言,OGNL 全稱 Object Graph Navigation Language 對象圖導航語言,是常應(yīng)用于 Java 中的一個開源的表達式語言(Expression Language),它被集成在 Spring、Mybatis、Struts2 等 Java 框架中,通過簡單一致的表達式語法,可以存取對象的任意屬性,調(diào)用對象的方法,遍歷整個對象的結(jié)構(gòu)圖,實現(xiàn)類型轉(zhuǎn)化等功能。
在書寫動態(tài) SQL 時經(jīng)常需要借助各種標簽,下面是一些在 mybatis 中常用的標簽:
if 標簽的 test 中常用判斷:
* 相等:==
* 不等:!=
* 條件或:or
* 條件與:and
* 條件非:!,也可以用 not
* 包含:in
* 不包含:not in
* 小于:<
* 小于等于:<=
* 大于:>
* 大于等于:>=
相當于 if、else if、else,間接實現(xiàn)了上面 if 標簽不支持的 else 效果
用于拼接 SQL 語句中的 where 子句,條件成立時才會加上 where 關(guān)鍵字,可以避免拼接出多余的and、or
<update id="updateUserInfo" parameterType="UserInfo">
update t_user_info
<set>
<if test="userName != null and userName != ''">
user_name = #{userName},
</if>
<if test="age != null">
age = #{age},
</if>
</set>
where user_id = #{userId}
</update>
可以間接實現(xiàn) where 和 set 標簽一樣的功能
遍歷集合類數(shù)據(jù),標簽屬性:
collection 接收的參數(shù):
<!-- mapper -->
int insertUsers(List<User> users);
int updateUsers(List<User> users);
<!-- xml -->
<insert id="insertUsers">
insert into t_user (id, user_name, age) values
<foreach collection="list" separator="," item="user">
(#{user.user_id}, #{user.user_name}, #{user.age})
</foreach>
</insert>
<update id="updateUsers">
<foreach collection="list" separator=";" item="user">
update t_user
<set>
<if test="user.userName != null and user.userName != ''">
user_name= #{user.userName},
</if>
<if test="user.age != null">
age= #{user.age},
</if>
</set>
where user_id = #{user.userId}
</foreach>
</update>
<!-- mapper -->
List<User> selectUsers(@Param("userIds") String[] userIds);
<!-- xml -->
<select id="selectUsers" resultType="User">
select * from t_user where user_id in
<foreach collection="userIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
更多參數(shù)傳遞可以參考后面的 mybatis 參數(shù)章節(jié)。
可以在 sql 標簽里定義語句,然后在需要的地方用 include 標簽引入進去,可以實現(xiàn)代碼片段復用。
用于配合插入數(shù)據(jù)成功后返回的數(shù)據(jù),一般用來返回 id 之類的。
主要有以下 5 種傳參方式:
xml 獲取的時候可以隨便寫,mybatis 會去自動處理,反正只有一個參數(shù)干脆就讓你寫啥都無所謂,不過推薦還是寫個有意義的形參:
<!-- mapper -->
User getUserByUsername(String userName);
<!-- xml -->
<select id="getUserByUsername" resultType="User">
select * from t_user where user_name = #{xxoo}
</select>
多個匿名參數(shù)的時候只能通過 mybatis 內(nèi)置的 param1、param2 按傳參順序?qū)?yīng):
<!-- mapper -->
List<User> selectByuserNameAndAge(String userName, Integer age);
<!-- xml -->
<select id="selectByuserNameAndAge" resultMap="BaseResultMap" >
select * from t_user where user_name = #{param1} and age = #{param2}
</select>
具名參數(shù)需要用 @Param 注解來指定
<!-- mapper -->
List<User> selectByuserNameAndAge(@Param("name") String userName, @Param("age") Integer age);
<!-- xml -->
<select id="selectByuserNameAndAge" resultMap="BaseResultMap" >
select * from t_user where user_name = #{name} and age = #{age}
</select>
List 類型參數(shù)默認值 list,Array 類型參數(shù)默認值 array,注意 Set 類型的默認值并不是 set 而是 collection,除此之外的集合默認值也是 collection,當然我們也可以用 @Param 注解來自己指定
<!-- mapper -->
List<User> selectByAgeList(List ages);
<!-- xml -->
<select id="selectByList" resultMap="BaseResultMap" >
SELECT * from t_user where age in
<foreach collection="list" open="(" separator="," close=")" item="age">
#{age}
</foreach>
</select>
使用 Map 參數(shù)時,可以直接用鍵名引用
Map params = new HashMap<>();
params.put("userName", "周小黑");
params.put("age", 18);
List<User> result = userMapper.selectByMapParams(params);
<!-- mapper -->
List<User> selectByMapParams(Map params);
<!-- xml -->
<select id="selectByMapParams" resultMap="BaseResultMap" parameterType="map">
select * from t_user where user_name = #{userName} and age = #{age}
</select>
和上面的 Map 比較類似,不過這里的 parameterType 要指定為對應(yīng)的 Bean 實體類型:
<!-- mapper -->
List<User> selectByBeans(User user);
<!-- xml -->
<select id="selectByBeans" resultMap="BaseResultMap" parameterType="User">
select * from t_user where user_name = #{userName} and age = #{age}
</select>
和上面的 Map、Bean 參數(shù)類似,一般是直接把前端傳遞過來的 json 參數(shù)直接傳入 Mapper 中進行查詢,parameterType 為 JSONObject
<!-- mapper -->
List<User> selectByJSON(JSONObject params);
<!-- xml -->
<select id="selectByJSON" resultMap="BaseResultMap" parameterType="com.alibaba.fastjson.JSONObject">
select * from t_user where user_name = #{userName} and age = #{age}
</select>
常見屬性設(shè)置:
XML 文件和我們常見的 HTML 類似,都是通過標簽來定義數(shù)據(jù),而尖括號本身就是表示標簽符號的開始和結(jié)束,所以在 mybatis 的 xml 文件中相關(guān)符號最好用轉(zhuǎn)義符,尤其小于符號 "<",這樣可以避免解析時報錯,常用轉(zhuǎn)義符:
字符名稱 sql符號 轉(zhuǎn)義字符
大于號 > >
小于號 < <
大于等于號 >= >=
小于等于號 <= <=
單引號 ' '
雙引號 " "
天學習了JS相關(guān)的基礎(chǔ)知識,了解了JS變量、常量的聲明,以及l(fā)et、const的區(qū)別,今天學習了字符串模板,發(fā)現(xiàn)這真是一個好東西,非常實用,下面我把今天所學的內(nèi)容總結(jié)梳理一下,把重點知識跟大家分享一下,也便于日后我復習所用。
模板字面量是在字符串中允許插入表達式的字符串字面量,我們可以使用多行字符串和字符串的插值功能。在ES2015(即:ES6)規(guī)范的先前版本中被稱為“模板字符串”。
` string `
` string ${expression} `
` string ${expression} string `
模板字符串是增強版的字符串(Plus+),使用反引號(` `)來替代普通字符串中的單雙引號,其中${expression}表示占位符。
注意在模板字符串中如果想使用反引號(`)需要加一個轉(zhuǎn)義符(\),即:\`
console.log('This is my first JS Code'); // This is my first JS Code
普通字符串
在以前的字符串中,如果我們想要多行字符串,需要用到換行符(\n),例如:
console.log('This is my first JS Code \n' +
'This is my second JS Code');
多行字符串
但是,現(xiàn)在可以利用模板字符串簡化這個問題:
console.log(`This is my first JS Code
This is my second JS Code`);
傳統(tǒng)的JS表達式需要這樣寫:
let num = 30;
let price = 100;
let res = '商品數(shù)量' + num + ', 單價:' + price + '元,總計:' + num * price;
使用上述傳統(tǒng)的表達式寫起來看著非常的亂,不直觀,有時候還容易把連接符(+)寫漏掉了,使用了ES6的模板字符串可以很好的避免這個問題:
res = `商品數(shù)量:${num},單價:${price},總計:${num * price}`;
console.log(res); // 商品數(shù)量:30,單價:100,總計:3000
以上結(jié)果都輸出:
商品數(shù)量:30,單價:100,總計:3000
標簽可以用函數(shù)來解析模板字符串。標簽函數(shù)的第一個參數(shù)是一個包含了字符串值的數(shù)組,剩余的參數(shù)與表達式相關(guān)。
let num = 10;
let price = 99;
function show(strings, var1, var2) {
console.log(strings);
console.log(var1, var2);
}
show `商品數(shù)量:${num}單價:${price}總計:${num * price}`;
由上圖可以看出,strings的值是一個由多組字符串組成的數(shù)組,va1,var2的值分別為num和price的值,由此結(jié)果可以很明顯的看到,在使用標簽函數(shù)時,模板字符串會被分割成多個部分,然后傳入標簽函數(shù)中進行處理,并且是以${expression}為分隔符進行分割的。從這個結(jié)論我們可以做一個總結(jié):
以上就是我所學的模板字符串的幾個常用的方法,總體感覺還不算是太難,上手很容易,根據(jù)我所學的內(nèi)容,我對模板字符串做了如下總結(jié):
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。