百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

SSM搭建二手市场交易平台(八)用户登录信息功能开发

toyiye 2024-06-21 12:27 7 浏览 0 评论

写在前面

本篇我们介绍用户登录获取信息,忘记密码,提示问题与答案,重置密码功能开发这四者的实现,里面的内容很多,希望大家对此有一个提前的认识。

还记得我们上一篇的UserController--->IUserService-->UserServiceImpl模式么,我们继续进行开发,把这个放在这里是让大家更清楚的知道我们的开发流程,不至于晕。

用户登录获取信息

打开UserController.java文件,写入以下代码:

 /***
 * 用户登录信息的获取
 * */
 @RequestMapping(value = "get_user_info.do",method = RequestMethod.GET) //这里就是具体的每个方法的url链接
 @ResponseBody //自动序列化json功能
 public ServerResponse<User> getUserInfo(HttpSession session){
 User user =(User) session.getAttribute(Const.CURRENT_USER);
 if(user != null){
 return ServerResponse.createBySuccess(user);
 }
 return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
 }

这样我们那就完成了用户登录信息的获取操作,你可能会问后面那两个过程哪去了,这里需要说明的是,不涉及到数据库的访问操作就不需要后面两个过程,这一点你需要注意一下。

忘记密码

打开UserController.java文件,写入以下代码:(注意我这里就是直接把这个功能的完整实现代码贴这里了,没有一步一步的写,毕竟太浪费时间了,也没有必要,你们懂我的意思吧)

 /***
 * 忘记密码
 * */
 @RequestMapping(value = "forget_get_question.do",method = RequestMethod.GET) //这里就是具体的每个方法的url链接
 @ResponseBody //自动序列化json功能
 public ServerResponse<String> forgetGetQuestion(String username){
 return iUserService.forgetGetQuestion(username);
 }

接着打开IUserService.java文件:

 ServerResponse<String> forgetGetQuestion(String username); //忘记密码

继续打开UserServiceImpl.java文件:

 /***
 *
 *忘记密码时的接口类
 * */
 public ServerResponse<String> forgetGetQuestion(String username){
 //判断用户名是否存在
 ServerResponse validResponse =this.checkValid(username,Const.USERNAME);
 if(validResponse.isSuccess()){ //用户名不存在
 return ServerResponse.createByErrorMessage("该用户不存在");
 }
 String question =userMapper.forgetgetQuestionByUsername(username);
 if(StringUtils.isNoneBlank(question)){
 //开始进行校验,如果找回密码的问题不为空,那么
 return ServerResponse.createBySuccess(question);
 }
 return ServerResponse.createByErrorMessage("找回密码的问题是空的");
 }
}

String question =userMapper.forgetgetQuestionByUsername(username);这行代码我需要说明一下。大家都知道我们这个UserMapper(里面的userMapper是它的实例化对象)就是DAO层,它需要提供一个接口(IUserService)和该接口的实现类(UserServiceImpl)用于访问数据库,但是我们获取数据库里面的信息是通过sql语句来实现的,于是UserMapper.xml负责sql语句的执行,UserMapper.java就负责接收查询的结果。因此就知道我们接下来要干嘛了:

打开UserMapper.java文件,里面新增代码:

String forgetgetQuestionByUsername(String username); //这里找不到对应的实现类,所以应该去UserMapper.xml里面进行配置

然后去UserMapper.xml里面新增代码:

 <select id="forgetgetQuestionByUsername" resultType="String" parameterType="String">
 select question from store_user
 where username = #{username}
</select>

也就是说实际上我们的开发顺序与上面所说的顺序是相反的,只是为了更好的理解。接下来完成提示问题与答案这个功能。

提示问题与答案

打开UserController.java文件,写入以下代码:

 /***
 * 提示问题与答案
 * */
 @RequestMapping(value = "forget_check_answer.do",method = RequestMethod.GET) //这里就是具体的每个方法的url链接
 @ResponseBody //自动序列化json功能
 public ServerResponse<String> checkAnswer(String username,String question,String answer){
 return iUserService.checkAnswer(username,question,answer);
 }

接着打开IUserService.java文件:

ServerResponse<String> checkAnswer(String username,String question,String answer); //提示问题与答案

继续打开UserServiceImpl.java文件:

 /***
 *
 *提示问题与答案时的接口类
 * */
 public ServerResponse<String> checkAnswer(String username,String question,String answer){
 int resultCount = userMapper.checkAnswer(username,question,answer); //根据用户名来检查用户设置的问题与答案是否存在
 if(resultCount >0){
 //说明提示问题及问题答案是这个用户的,并且是正确的
 String forgetToken = UUID.randomUUID().toString();
 TockenCache.setKey("token_"+username,forgetToken);
 return ServerResponse.createBySuccess(forgetToken);
 }
 return ServerResponse.createByErrorMessage("问题的答案错误!");
 }

同样checkAnswer这个方法需要定义,打开UserMapper.java文件,里面新增代码:

 //这里找不到对应的实现类,所以应该去UserMapper.xml里面进行配置
 int checkAnswer(@Param("username")String username,@Param("question")String question,@Param("answer")String answer); //注意mybatis传递多个参数时,需要使用param注解

然后去UserMapper.xml里面新增代码:

<select id="checkAnswer" resultType="int" parameterType="map"> <!--注意使用多个参数是是需要使用map的-->
 select count(1) from store_user
 where username = #{username}
 and question = #{question}
 and answer = #{answer}
</select>

还有因为我们这个提示问题与答案是需要写入cache的,因此我们需要在common包下面新建一个类,里面写入如下代码:

package top.store.common;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
public class TockenCache {
 private static Logger logger = LoggerFactory.getLogger(TockenCache.class);
 //本地缓存
 //这里采用了LRU算法,初始值是1000,最大值是10000,如果超过最大值就会使用LRU算法进行消除,其实就是删除使用频率低的值,它的有效时间为12个小时
 private static LoadingCache<String,String> localCache = CacheBuilder.newBuilder().initialCapacity(1000).maximumSize(10000).expireAfterAccess(12, TimeUnit.HOURS).build(new CacheLoader<String, String>(){
 @Override
 public String load(String s) throws Exception {
 return "null";
 }
 });
 public static void setKey(String key,String value){
 localCache.put(key,value);
 }
 public static String getKey(String key){
 String value = null;
 try{
 value = localCache.get(key);
 if("null".equals(value)){
 return null;
 }
 return value;
 }catch (Exception e){
 logger.error("localCache get error",e);
 }
 return null;
 }
}

接下来便是忘记密码中的重置密码的开发了,我们知道这个必须在忘记密码实现以后才能开始。

重置密码

打开UserController.java文件,写入以下代码:

 /***
 *
 * 忘记密码中的重置密码
 */
 @RequestMapping(value = "forget_reset_password.do",method = RequestMethod.GET) //这里就是具体的每个方法的url链接
 @ResponseBody //自动序列化json功能
 public ServerResponse<String> forgetResetPassword(String username,String passwordNew, String forgetToken){
 return iUserService.forgetResetPassword(username,passwordNew,forgetToken);
 }

接着打开IUserService.java文件:

ServerResponse<String> forgetResetPassword(String username,String passwordNew, String forgetToken); //忘记密码中的重置密码

继续打开UserServiceImpl.java文件:

/***
 *
 * 忘记密码中的重置密码的接口类
 */
 public ServerResponse<String> forgetResetPassword(String username,String passwordNew, String forgetToken){
 //首先进行token的校验
 if(StringUtils.isBlank(forgetToken)){ //如果token是空的话
 return ServerResponse.createByErrorMessage("参数错误,token还没有被传递呢");
 }
 //这里我们需要校验username,因为forgetToken是通过token_与username进行拼接的,上面是验证了forgetToken不为空,但这并不代表username就不为空
 ServerResponse validResponse =this.checkValid(username,Const.USERNAME);
 if(validResponse.isSuccess()){ //用户名不存在
 return ServerResponse.createByErrorMessage("该用户不存在");
 }
 String token = TockenCache.getKey(TockenCache.TOKEN_PREFIX+username); //可以参看第146行代码
 //对caChe里的token进行校验
 if(StringUtils.isBlank(token)){
 return ServerResponse.createByErrorMessage("token无效或者过期");
 }
 /***
 String a = null;
 if("abc".equals(a)){} //总是错误
 if(a.equals("abc")){} //引发空指针异常
 */
 //这里使用.equals方法,可以避免出现Null值在前的空指针,在后总是错误的问题
 if(StringUtils.equals(forgetToken,token)){
 //修改密码成功,我们需要更新旧的密码了
 String md5Password = MD5Util.MD5EncodeUtf8(passwordNew);
 int rowCount = userMapper.updatePasswordByUsername(username,md5Password);
 if(rowCount>0){
 return ServerResponse.createBySuccessMassage("密码修改成功!");
 }
 }else{
 return ServerResponse.createByErrorMessage("token错误,请重新获取重置密码的token");
 }
 return ServerResponse.createByErrorMessage("密码修改失败!");
 }

这里面有几个注意的事项:

1、"token_"这个之前在写提示问题与答案时的接口类时,没有将其设定为一个常量,实际上它是一个常量,为了以后便于调用它,我们将其设定为一个常量:

打开TockenCache.java文件,我们新增一行代码:

public static final String TOKEN_PREFIX = "token_"; //这里把token_作为一个常量。因为需要多次使用

然后你将checkAnswer方法里面的这行代码:

ockenCache.setKey("token_"+username,forgetToken); //这里没有把token_当做一个全局的常量进行引用

替换为:

TockenCache.setKey(TockenCache.TOKEN_PREFIX+username,forgetToken); // 这里把token_当做一个全局的常量进行引用(在TockenCache.TOKEN_PREFIX里面)

2、StringUtils.equals(forgetToken,token)注意这里我们使用了StringUtils.equals方法,它最大的好处就是可以避免null值在前在后的问题:

 public static boolean equals(CharSequence cs1, CharSequence cs2) {
 if (cs1 == cs2) {
 return true;
 } else if (cs1 != null && cs2 != null) {
 if (cs1.length() != cs2.length()) {
 return false;
 } else {
 return cs1 instanceof String && cs2 instanceof String ? cs1.equals(cs2) : CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, cs1.length());
 }
 } else {
 return false;
 }
 }

那么什么是null值在前在后的问题呢?很简单我举个例子你就知道了:

String a = null;
if("abc".equals(a)){} //总是错误
if(a.equals("abc")){} //引发空指针异常

所以这个问题我们就可以不用考虑了。

3、int rowCount = userMapper.updatePasswordByUsername(username,md5Password);这行代码中的updatePasswordByUsername方法,老规矩还是需要定义这个方法,打开UserMapper.java文件,里面新增代码:

 //这里找不到对应的实现类,所以应该去UserMapper.xml里面进行配置
 int updatePasswordByUsername(@Param("username")String username,@Param("passwordNew")String passwordNew); //注意mybatis传递多个参数时,需要使用param注解

然后去UserMapper.xml里面新增代码:

<update id="updatePasswordByUsername" parameterType="map"> <!--注意使用多个参数是是需要使用map的,而且这里因为是更新操作,因此需要使用update-->
 update store_user
 set password =#{passwordNew},update_time =now()
 where username = #{username}
</update>

这段代码因为是执行更新操作的,因此需要使用update,而且别忘记使用update_time =now()这个时间戳,否则你不知道具体什么时候修改了密码。

4、至于为什么我们每次判断的时候总是看它大于0或者等于0,那是因为我们使用的方法最后我们都是让它返回修改的行数(其实就是受影响的行数),如果为0就说明没有修改,否则就进行了修改,这个应该很好理解的吧。

这样,我们本篇关于用户登录获取信息,忘记密码,提示问题与答案,重置密码功能开发这四者的介绍就到此为止了,感谢你的赏阅!

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码