0
点赞
收藏
分享

微信扫一扫

《果然新鲜》电商项目(31)- 门户登出功能

40dba2f2a596 2022-06-30 阅读 63


文章目录

  • ​​引言​​
  • ​​1.功能演示及实现思路​​
  • ​​2. 登出功能​​
  • ​​2.1 前端代码​​
  • ​​2.2 后端代码​​
  • ​​3. 遇到的坑​​
  • ​​3.1 JQ ajax请求后台不能“请求转发”或者“重定向”​​
  • ​​3.2 JQ ajax 返回格式的指定格式​​
  • ​​4.总结​​

引言

在前面实现了「注册」和「登录」的功能,本文主要讲解“登出功能”,虽然功能看上去比较简单,但是遇到了不少的坑。

1.功能演示及实现思路

实现思路:

  1. 会员登录成功后,点击主页面右上角的退出,请求后台
  2. 后台删除Cookie信息里面的token
  3. 后台根据token删除Redis里保存的token
  4. 后台根据token更新数据库里面对应的token记录

功能演示:

  1. 首先登录,登录成功后,界面如下:
    《果然新鲜》电商项目(31)- 门户登出功能_ajax

2.登录成功后,可以看到Redis和数据库均有内容:

redis
《果然新鲜》电商项目(31)- 门户登出功能_json_02
数据库
《果然新鲜》电商项目(31)- 门户登出功能_前端_03
3.点击右上角的退出,点击完后,可以看到自动跳转到主页面:

点击前
《果然新鲜》电商项目(31)- 门户登出功能_ajax点击后
《果然新鲜》电商项目(31)- 门户登出功能_spring_05
4.同时Redis和数据库里的内容均有改变:

redis
《果然新鲜》电商项目(31)- 门户登出功能_前端_06
数据库
《果然新鲜》电商项目(31)- 门户登出功能_spring_07

2. 登出功能

2.1 前端代码

前端使用的是jq的ajax请求,使用的是RESTful标准请求,代码如下:

html代码:

<li th:if="${desensMobile!=null}"><a href="javascript:void(0);" onclick="logout();">退出</a></li>

js代码:

<!--引入JQuery-->
<script type="text/javascript" src="plugins/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
function logout() {
$.ajax({
type: "delete",
url: "exit",
contentType: "application/json",
dataType: "json",
success: function (result) {
window.location.href = "/";
},
error: function (result) {
}
});
}
</script>

2.2 后端代码

MemberLogoutServiceFeign

package com.guoranxinxian.member.feign;

import com.guoranxinxian.service.MemberLogOutService;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient("guoranxinxian-shop-service-member")
public interface MemberLogoutServiceFeign extends MemberLogOutService {

}

控制层(使用的是Feign远程调用):

package com.guoranxinxian.member.controller;

import com.alibaba.fastjson.JSONObject;
import com.guoranxinxian.api.BaseResponse;
import com.guoranxinxian.common.base.BaseWebController;
import com.guoranxinxian.common.constants.WebConstants;
import com.guoranxinxian.common.util.CookieUtils;
import com.guoranxinxian.member.feign.MemberLogoutServiceFeign;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class LogoutController extends BaseWebController {

@Autowired
private MemberLogoutServiceFeign memberLogoutServiceFeign;


@DeleteMapping("/exit")
@ResponseBody
public BaseResponse<JSONObject> exit(HttpServletRequest request, HttpServletResponse response, Model model) {
// 1.从cookie 中 获取 会员token
String token = CookieUtils.getCookieValue(request, WebConstants.LOGIN_TOKEN_COOKIENAME, true);
CookieUtils.deleteCookie(request, response, WebConstants.LOGIN_TOKEN_COOKIENAME);
if (!StringUtils.isEmpty(token)) {
// 2.调用登出服务接口
return memberLogoutServiceFeign.logout(token);
}
return null;
}
}

MemberLogOutService

package com.guoranxinxian.service;

import com.alibaba.fastjson.JSONObject;
import com.guoranxinxian.api.BaseResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

/**
* description: 用户登出接口
*/
@Api(tags = "用户登出服务接口")
public interface MemberLogOutService {
/**
* 用户登出接口
*
* @param token
* @return
*/
@DeleteMapping("/logout")
@ApiOperation(value = "/logout")
BaseResponse<JSONObject> logout(@RequestParam("token") String token);

}

MemberLogOutServiceImpl

package com.guoranxinxian.impl;

import com.alibaba.fastjson.JSONObject;
import com.guoranxinxian.api.BaseResponse;
import com.guoranxinxian.entity.BaseApiService;
import com.guoranxinxian.mapper.UserTokenMapper;
import com.guoranxinxian.service.MemberLogOutService;
import com.guoranxinxian.util.GenerateToken;
import com.guoranxinxian.util.RedisDataSoureceTransaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemberLogOutServiceImpl extends BaseApiService<JSONObject> implements MemberLogOutService {

@Autowired
private GenerateToken generateToken;

@Autowired
private UserTokenMapper userTokenMapper;
/**
* 手动事务工具类
*/
@Autowired
private RedisDataSoureceTransaction manualTransaction;

@Override
public BaseResponse<JSONObject> logout(String token) {
TransactionStatus transactionStatus = null;
try {
transactionStatus = manualTransaction.begin();
//2.删除Redis
generateToken.removeToken(token);
//1.首先更新数据库
int updateTokenAvailability = userTokenMapper.updateTokenAvailability(token);
if (updateTokenAvailability < 0) {
manualTransaction.rollback(transactionStatus);
return setResultError("系统错误");
}
manualTransaction.commit(transactionStatus);
JSONObject data = new JSONObject();
data.put("result", true);
return setResultSuccess(data);
} catch (Exception e) {
try {
// 回滚事务
manualTransaction.rollback(transactionStatus);
} catch (Exception e1) {
}
return setResultError("系统错误!");
}
}
}

3. 遇到的坑

3.1 JQ ajax请求后台不能“请求转发”或者“重定向”

调用后台登出接口的时候,如果直接返回​​redirect:/​​,前端页面是不会直接跳转到的,这是为什么呢?

因为JQ使用ajax是禁止后台执行“请求转发”或者“重定向”的,只能后台返回数据,由前端使用​​window.location.href​​执行页面的跳转。如下代码:

$.ajax({
type: "delete",
url: "exit",
contentType: "application/json",
dataType: "json",
success: function (result) {
window.location.href = "/";
},
error: function (result) {
}
});
}
);

3.2 JQ ajax 返回格式的指定格式

在上面代码,可以看到,​​ajax​​​指定返回的格式为​​json​​​,因此别忘记了在接口处添加​​@ResponseBody​​​注解:
《果然新鲜》电商项目(31)- 门户登出功能_spring_08

4.总结

本文主要讲解了 「登出」 的功能,虽然流程不复杂,但是里面涉及到了很多的基础知识,如​​RESTful​​​,​​JQ ajax​​请求注意细节等。


举报

相关推荐

0 条评论