在實現RememberMe時遇到如下錯誤
2019-06-24 15:37:49.620 WARN 12952 --- [nio-8088-exec-2] o.a.shiro.mgt.DefaultSecurityManager : Delegate RememberMeManager instance of type [org.apache.shiro.web.mgt.CookieRememberMeManager] threw an exception during onSuccessfulLogin. RememberMe services will not be performed for account [com.sfn.bms.system.model.User@86fc436].
org.apache.shiro.io.SerializationException: Unable to serialize object [com.sfn.bms.system.model.User@86fc436]. In order for the DefaultSerializer to serialize this object, the [org.apache.shiro.subject.SimplePrincipalCollection] class must implement java.io.Serializable.
查找了下原因,原來使用Generator生成的User是沒有序列化的
package com.sfn.bms.system.model; import javax.persistence.*; public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Short id; /** * 賬號 */ private String account; /** * 密碼 */ private String password; /** * 郵箱 */ private String email; /** * 狀態 1-正常,0-禁用,-1-刪除 */ private Boolean status; /** * 添加時間 */ @Column(name = "create_time") private Integer createTime; /** * 上次登陸時間 */ @Column(name = "last_login_time") private Integer lastLoginTime; /** * 上次登錄IP */ @Column(name = "last_login_ip") private String lastLoginIp; /** * 登陸次數 */ @Column(name = "login_count") private Integer loginCount; /** * @return id */ public Short getId() { return id; } /** * @param id */ public void setId(Short id) { this.id = id; } /** * 獲取賬號 * * @return account - 賬號 */ public String getAccount() { return account; } /** * 設置賬號 * * @param account 賬號 */ public void setAccount(String account) { this.account = account == null ? null : account.trim(); } /** * 獲取密碼 * * @return password - 密碼 */ public String getPassword() { return password; } /** * 設置密碼 * * @param password 密碼 */ public void setPassword(String password) { this.password = password == null ? null : password.trim(); } /** * 獲取郵箱 * * @return email - 郵箱 */ public String getEmail() { return email; } /** * 設置郵箱 * * @param email 郵箱 */ public void setEmail(String email) { this.email = email == null ? null : email.trim(); } /** * 獲取狀態 1-正常,0-禁用,-1-刪除 * * @return status - 狀態 1-正常,0-禁用,-1-刪除 */ public Boolean getStatus() { return status; } /** * 設置狀態 1-正常,0-禁用,-1-刪除 * * @param status 狀態 1-正常,0-禁用,-1-刪除 */ public void setStatus(Boolean status) { this.status = status; } /** * 獲取添加時間 * * @return create_time - 添加時間 */ public Integer getCreateTime() { return createTime; } /** * 設置添加時間 * * @param createTime 添加時間 */ public void setCreateTime(Integer createTime) { this.createTime = createTime; } /** * 獲取上次登陸時間 * * @return last_login_time - 上次登陸時間 */ public Integer getLastLoginTime() { return lastLoginTime; } /** * 設置上次登陸時間 * * @param lastLoginTime 上次登陸時間 */ public void setLastLoginTime(Integer lastLoginTime) { this.lastLoginTime = lastLoginTime; } /** * 獲取上次登錄IP * * @return last_login_ip - 上次登錄IP */ public String getLastLoginIp() { return lastLoginIp; } /** * 設置上次登錄IP * * @param lastLoginIp 上次登錄IP */ public void setLastLoginIp(String lastLoginIp) { this.lastLoginIp = lastLoginIp == null ? null : lastLoginIp.trim(); } /** * 獲取登陸次數 * * @return login_count - 登陸次數 */ public Integer getLoginCount() { return loginCount; } /** * 設置登陸次數 * * @param loginCount 登陸次數 */ public void setLoginCount(Integer loginCount) { this.loginCount = loginCount; } }
而這里User需要實現序列化,所以要實現Serializable類
解決方案:
MyBatis Generator提供了SerializablePlugin插件用來在代碼生成時實現序列化
使用:在配置文件 mybatis-generator.xml 中 SerializablePlugin 插件,添加
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
完整的配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3Simple" defaultModelType="flat"> <plugin type="org.mybatis.generator.plugins.SerializablePlugin" /> <plugin type="tk.mybatis.mapper.generator.MapperPlugin"> <!-- 該配置會使生產的Mapper自動繼承MyMapper --> <property name="mappers" value="com.sfn.bms.common.config.MyMapper" /> <!-- caseSensitive默認false,當數據庫表名區分大小寫時,可以將該屬性設置為true --> <property name="caseSensitive" value="false"/> </plugin> <!-- 阻止生成自動注釋 --> <commentGenerator> <property name="javaFileEncoding" value="UTF-8"/> <property name="suppressDate" value="true"/> <property name="suppressAllComments" value="true"/> </commentGenerator> <!-- 數據庫鏈接地址賬號密碼 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/bms?serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true" userId="root" password="root"> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- 生成Model類存放位置 --> <javaModelGenerator targetPackage="com.sfn.bms.system.model" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- 生成映射文件存放位置 --> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- 生成Dao類存放位置 --> <!-- 客戶端代碼,生成易於使用的針對Model對象和XML配置文件的代碼 type="ANNOTATEDMAPPER",生成Java Model 和基於注解的Mapper對象 type="XMLMAPPER",生成SQLMap XML文件和獨立的Mapper接口 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.sfn.bms.system.mapper" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 配置需要生成的表 --> <table tableName="USER" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> <generatedKey column="id" sqlStatement="mysql" identity="true"/> </table> </context> </generatorConfiguration>
重新執行generator,生成User
package com.sfn.bms.system.model; import java.io.Serializable; import javax.persistence.*; public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Short id; /** * 賬號 */ private String account; /** * 密碼 */ private String password; /** * 郵箱 */ private String email; /** * 狀態 1-正常,0-禁用,-1-刪除 */ private Boolean status; /** * 添加時間 */ @Column(name = "create_time") private Integer createTime; /** * 上次登陸時間 */ @Column(name = "last_login_time") private Integer lastLoginTime; /** * 上次登錄IP */ @Column(name = "last_login_ip") private String lastLoginIp; /** * 登陸次數 */ @Column(name = "login_count") private Integer loginCount; private static final long serialVersionUID = 1L; /** * @return id */ public Short getId() { return id; } /** * @param id */ public void setId(Short id) { this.id = id; } /** * 獲取賬號 * * @return account - 賬號 */ public String getAccount() { return account; } /** * 設置賬號 * * @param account 賬號 */ public void setAccount(String account) { this.account = account == null ? null : account.trim(); } /** * 獲取密碼 * * @return password - 密碼 */ public String getPassword() { return password; } /** * 設置密碼 * * @param password 密碼 */ public void setPassword(String password) { this.password = password == null ? null : password.trim(); } /** * 獲取郵箱 * * @return email - 郵箱 */ public String getEmail() { return email; } /** * 設置郵箱 * * @param email 郵箱 */ public void setEmail(String email) { this.email = email == null ? null : email.trim(); } /** * 獲取狀態 1-正常,0-禁用,-1-刪除 * * @return status - 狀態 1-正常,0-禁用,-1-刪除 */ public Boolean getStatus() { return status; } /** * 設置狀態 1-正常,0-禁用,-1-刪除 * * @param status 狀態 1-正常,0-禁用,-1-刪除 */ public void setStatus(Boolean status) { this.status = status; } /** * 獲取添加時間 * * @return create_time - 添加時間 */ public Integer getCreateTime() { return createTime; } /** * 設置添加時間 * * @param createTime 添加時間 */ public void setCreateTime(Integer createTime) { this.createTime = createTime; } /** * 獲取上次登陸時間 * * @return last_login_time - 上次登陸時間 */ public Integer getLastLoginTime() { return lastLoginTime; } /** * 設置上次登陸時間 * * @param lastLoginTime 上次登陸時間 */ public void setLastLoginTime(Integer lastLoginTime) { this.lastLoginTime = lastLoginTime; } /** * 獲取上次登錄IP * * @return last_login_ip - 上次登錄IP */ public String getLastLoginIp() { return lastLoginIp; } /** * 設置上次登錄IP * * @param lastLoginIp 上次登錄IP */ public void setLastLoginIp(String lastLoginIp) { this.lastLoginIp = lastLoginIp == null ? null : lastLoginIp.trim(); } /** * 獲取登陸次數 * * @return login_count - 登陸次數 */ public Integer getLoginCount() { return loginCount; } /** * 設置登陸次數 * * @param loginCount 登陸次數 */ public void setLoginCount(Integer loginCount) { this.loginCount = loginCount; } }
前后生成User的區別:
1.實現了Serializable接口
2.增加了private static final long serialVersionUID = 1L;
問題解決
