天,有渔老师去现场为一位朋友解决一个网站注册验证的问题。问题是这样的:在朋友的网站用邮箱注册后,系统会发一封邮件到邮箱,然后点击链接设置账号的初始化密码。如下图所示:
但我点击这个链接后,wordpress一直提示invalid key,也就是说key错误。因为是wordpress框架,从url的路由看,我就打开wp-login.php,然后查看其中的action rp。我直观感觉,应该是get url中的key跟数据库中的key值不相等导致的。所以,想进入系统的mysql一查究竟,但遗憾的是竟然没有mysql权限,我也不知道他的网站是让谁做的,估计是个外包吧。因为朋友是不懂技术的,很多事情问他也是一问三不知。没办法,哪就自己闷头搞吧。
外事不决问google,内事不决问baidu。我习惯性地打开baidu,输入:wordpress新用户注册 key无效。发现碰到类似问题的同行也不少,且看他们是如何解决的?他们的建议是:
编辑wp-includes文件夹中的pluggable.php文件,把变量$message里的>符合去掉。我照做了,发现还是不行的哦。所以,网上的东西,很多都得自己再实践下,否则是要被坑的。但到这一步,我更加确信是key的值出问题了。然后我又仔细看了下邮件发送过来的链接,发现这个链接有个问题。
这个链接里的&是&被转义后的值。那么,我在浏览器里输入时把&替换成&会怎样呢?发现竟然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后面的&怎么没被转义,而$key后面的&却被转义了。所以,到这一步,我就怀疑是不是语句的顺序有问题?然后,我就把&key=$key放到($user->user_login)后面。然后,根据前面baidu的一些意见,顺便把<和>符合也去掉。这样,修改后的message如下:
$message .= network_site_url(“wp-login.php?action=rp&login=” . rawurlencode($user->user_login)."&key=$key", ‘login’) . “\r\n\r\n”;
问题就这样解决了。
总结:1,出现问题,问baidu一般都能找到一些建议。但这些建议不一定完全正确,自己还得根据实际情况修改。2,html的一些特殊符号,在存数据库之前需要被转义,在取出数据库后,需要被转换回来,这也是一个很重要的知识点。
mybatis 的 xml 文件里写的 sql 语句实际用的是一门叫做 OGNL 的表达式语言,OGNL 全称 Object Graph Navigation Language 对象图导航语言,是常应用于 Java 中的一个开源的表达式语言(Expression Language),它被集成在 Spring、Mybatis、Struts2 等 Java 框架中,通过简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现类型转化等功能。
在书写动态 SQL 时经常需要借助各种标签,下面是一些在 mybatis 中常用的标签:
if 标签的 test 中常用判断:
* 相等:==
* 不等:!=
* 条件或:or
* 条件与:and
* 条件非:!,也可以用 not
* 包含:in
* 不包含:not in
* 小于:<
* 小于等于:<=
* 大于:>
* 大于等于:>=
相当于 if、else if、else,间接实现了上面 if 标签不支持的 else 效果
用于拼接 SQL 语句中的 where 子句,条件成立时才会加上 where 关键字,可以避免拼接出多余的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>
可以间接实现 where 和 set 标签一样的功能
遍历集合类数据,标签属性:
collection 接收的参数:
<!-- 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>
更多参数传递可以参考后面的 mybatis 参数章节。
可以在 sql 标签里定义语句,然后在需要的地方用 include 标签引入进去,可以实现代码片段复用。
用于配合插入数据成功后返回的数据,一般用来返回 id 之类的。
主要有以下 5 种传参方式:
xml 获取的时候可以随便写,mybatis 会去自动处理,反正只有一个参数干脆就让你写啥都无所谓,不过推荐还是写个有意义的形参:
<!-- mapper -->
User getUserByUsername(String userName);
<!-- xml -->
<select id="getUserByUsername" resultType="User">
select * from t_user where user_name = #{xxoo}
</select>
多个匿名参数的时候只能通过 mybatis 内置的 param1、param2 按传参顺序对应:
<!-- 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>
具名参数需要用 @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 类型参数默认值 list,Array 类型参数默认值 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 参数时,可以直接用键名引用
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 要指定为对应的 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 参数类似,一般是直接把前端传递过来的 json 参数直接传入 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>
常见属性设置:
XML 文件和我们常见的 HTML 类似,都是通过标签来定义数据,而尖括号本身就是表示标签符号的开始和结束,所以在 mybatis 的 xml 文件中相关符号最好用转义符,尤其小于符号 "<",这样可以避免解析时报错,常用转义符:
字符名称 sql符号 转义字符
大于号 > >
小于号 < <
大于等于号 >= >=
小于等于号 <= <=
单引号 ' '
双引号 " "
天学习了JS相关的基础知识,了解了JS变量、常量的声明,以及let、const的区别,今天学习了字符串模板,发现这真是一个好东西,非常实用,下面我把今天所学的内容总结梳理一下,把重点知识跟大家分享一下,也便于日后我复习所用。
模板字面量是在字符串中允许插入表达式的字符串字面量,我们可以使用多行字符串和字符串的插值功能。在ES2015(即:ES6)规范的先前版本中被称为“模板字符串”。
` string `
` string ${expression} `
` string ${expression} string `
模板字符串是增强版的字符串(Plus+),使用反引号(` `)来替代普通字符串中的单双引号,其中${expression}表示占位符。
注意在模板字符串中如果想使用反引号(`)需要加一个转义符(\),即:\`
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');
多行字符串
但是,现在可以利用模板字符串简化这个问题:
console.log(`This is my first JS Code
This is my second JS Code`);
传统的JS表达式需要这样写:
let num = 30;
let price = 100;
let res = '商品数量' + num + ', 单价:' + price + '元,总计:' + num * price;
使用上述传统的表达式写起来看着非常的乱,不直观,有时候还容易把连接符(+)写漏掉了,使用了ES6的模板字符串可以很好的避免这个问题:
res = `商品数量:${num},单价:${price},总计:${num * price}`;
console.log(res); // 商品数量:30,单价:100,总计:3000
以上结果都输出:
商品数量:30,单价:100,总计:3000
标签可以用函数来解析模板字符串。标签函数的第一个参数是一个包含了字符串值的数组,剩余的参数与表达式相关。
let num = 10;
let price = 99;
function show(strings, var1, var2) {
console.log(strings);
console.log(var1, var2);
}
show `商品数量:${num}单价:${price}总计:${num * price}`;
由上图可以看出,strings的值是一个由多组字符串组成的数组,va1,var2的值分别为num和price的值,由此结果可以很明显的看到,在使用标签函数时,模板字符串会被分割成多个部分,然后传入标签函数中进行处理,并且是以${expression}为分隔符进行分割的。从这个结论我们可以做一个总结:
以上就是我所学的模板字符串的几个常用的方法,总体感觉还不算是太难,上手很容易,根据我所学的内容,我对模板字符串做了如下总结:
*请认真填写需求信息,我们会在24小时内与您取得联系。