引言
本文代码已提交至Github(版本号:
42c2ed4af58dac7388e399a1f3606baf4c57744e
),有兴趣的同学可以下载来看看:https://github.com/ylw-github/taodong-shop
在前面的两篇博客,实现了「注册」和「登录」的功能:
本文主要讲解“登出功能”,虽然功能看上去比较简单,但是遇到了不少的坑。
本文目录结构:
l________ 3.1 JQ ajax请求后台不能“请求转发”或者“重定向”
l________ 3.2 JQ ajax 返回格式的指定格式
1. 功能演示及实现思路
实现思路:
- 会员登录成功后,点击主页面右上角的退出,请求后台
- 后台删除Cookie信息里面的token
- 后台根据token删除Redis里保存的token
- 后台根据token更新数据库里面对应的token记录
功能演示:
1.首先登录,登录成功后,界面如下:
2.登录成功后,可以看到Redis和数据库均有内容:
redis | 数据库 |
3.点击右上角的退出,点击完后,可以看到自动跳转到主页面:
点击前 | 点击后 |
4.同时Redis和数据库里的内容均有改变:
Redis | 数据库 |
2. 登出功能
2.1 前端代码
前端我使用的是jq的ajax
请求,使用的是RESTful标准请求(如果对RESTful不清楚,可以参考我的博客:《RESTful Web 服务四种操作POST/DELETE/PUT/GET》),代码如下:
html代码:
<a href="javascript:void(0);" onclick="logout();">退出</a>
js代码:
<!--引入JQuery--> <script src="../res/static/js/jquery.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 后端代码
控制层(使用的是Feign远程调用):
@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; } }
会员服务里面的登出接口实现(使用的是Redis与数据库的事务同步工具类,不懂的可以下载代码看,前面的文章已讲过):
@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
注解:
总结
本文主要讲解了 「登出」 的功能,虽然流程不复杂,但是里面涉及到了很多的基础知识,如RESTful
,JQ ajax
请求注意细节等。