目录
一、前言
前几天我们已经实现了通过邮箱注册账号的功能,注册之后当然就是要登录。但是我们没有网站后台,所以现在暂时把所有的登录成功的请求转到博客首页。我最近几天把数据库表重新设计了一下,对应着项目的mapper文件也有一定的修改,文章在这里不再细说,如果有兴趣跟着一起创建一个属于自己的博客的话,可以去我的GitHub主页下载一下代码,里面也有数据库的内容。
二、功能实现
1.controller
登录功能的在UserLoginController.java下实现,具体的映射路径是/user/login.action,我们在登录界面填写表单后,数据就会请求到这个接口
@RequestMapping(value = "/login.action")
@ApiOperation(value = "登录接口", notes = "进入登录界面", response = ModelAndView.class)
ModelAndView userLogin(HttpServletRequest request) {
ModelAndView mv = new ModelAndView();
Map<String, String> paramMap = RequestUtil.getRequestParamMap(request);
//减少controller中的代码,提高程序复用
JSONObject retJSon = userService.doLogin(paramMap);
HttpSession session = request.getSession();
//session过期时间
session.setMaxInactiveInterval(5 * 30);
if (paramMap.get("remember").equals("1")) session.setMaxInactiveInterval(-1);
session.setAttribute("loginUser", retJSon.get("user"));
request.setAttribute("msg", retJSon.get("msg"));
mv.setViewName(retJSon.getString("viewName"));
return mv;
}
2.service
查了一下资料,说的是controller中的代码应当尽量地少,他做的是应当是以下三个:
-
在初始化时,构造相应的 View 和 Model。
-
监听 Model 层的事件,将 Model 层的数据传递到 View 层。
-
监听 View 层的事件,并且将 View 层的事件转发到 Model 层。
所以在这里,我们将登录验证写到了UserService里,提高代码复用,从你我做起
@Override
public JSONObject doLogin(Map<String, String> paramMap) {
JSONObject retJson = new JSONObject();
retJson.put("msg", null);
retJson.put("viewName", "forward:/index.jsp");
retJson.put("user", null);
String email = paramMap.containsKey("email") ? paramMap.get("email") : "nothing";
String password = paramMap.containsKey("password") ? paramMap.get("password") : "nothing";
Criteria criteria = new Criteria();
criteria.put("email", email);
ArrayList<User> users = getList(criteria);
if (users.size() == 0) {
retJson.put("retCode", "404");
retJson.put("msg", "邮箱不存在,请检查邮箱后重新输入!");
retJson.put("viewName", "forward:/login/index.jsp");
return retJson;
}
User user = users.get(0);
if (!password.equals(user.getUserPassword())) {
retJson.put("retCode", "304");
retJson.put("msg", "密码不正确,请检查密码后重新输入!");
retJson.put("viewName", "forward:/login/index.jsp");
return retJson;
}
retJson.put("user", user);
return retJson;
}
3.mapper
新增了一个获取userList的接口,用于获取符合某些条件的user
<select id="getList" resultMap="BaseResultMap" parameterType="cn.yzstu.common.Criteria">
select * from yz_users
<if test="_parameter != null">
<include refid="getUserListSql"/>
</if>
</select>
<select id="getById" resultMap="BaseResultMap" parameterType="java.lang.Long">
select
<include refid="Base_Column_List"/>
from yz_users
where user_id = #{userId,jdbcType=BIGINT}
</select>
4.Criteria.java查找工具类
这个工具类通用各种查找,具体用法可以自己看,或者问我,感觉在博客里解释不清楚
package cn.yzstu.common;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* \* Created with IntelliJ IDEA.
* \* User: Baldwin
* \* E_Mail: [email protected] || [email protected]
* \* Date: 2019/12/16
* \* Time: 19:11
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class Criteria {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 存放条件查询值
*/
private Map<String, Object> condition;
/**
* 存放所要获取的字段的值,也可可以多为其他使用,灵活但注意安全!!!
*/
private Map<String, Object> targetColums;
/**
* 存放查询时多个条件,便于遍历
*/
private List<String> conditionList;
/**
* 是否相异
*/
protected boolean distinct;
/**
* 排序字段
*/
protected String orderByClause;
private Integer mysqlOffset;
private Integer mysqlLength;
protected Criteria(Criteria example) {
this.orderByClause = example.orderByClause;
this.condition = example.condition;
this.distinct = example.distinct;
this.mysqlLength = example.mysqlLength;
this.mysqlOffset = example.mysqlOffset;
}
public Criteria() {
condition = new HashMap<String, Object>();
targetColums = new HashMap<String, Object>();
conditionList = new ArrayList<String>();
}
public void clear() {
condition.clear();
orderByClause = null;
distinct = false;
this.mysqlOffset = null;
this.mysqlLength = null;
}
/**
* @param condition 查询的条件名称
* @param value 查询的值
*/
public Criteria put(String condition, Object value) {
this.condition.put(condition, value);
return (Criteria) this;
}
/**
* @param targetColum 需要返回的列
* @return
*/
public Criteria putTarget(String targetColum) {
this.targetColums.put(targetColum, targetColum);
return (Criteria) this;
}
public Criteria setTargetColums(Map<String, Object> map) {
this.targetColums = map;
return (Criteria) this;
}
public List<String> getConditionList() {
return conditionList;
}
public Criteria putConditionList(List<String> conditionList) {
this.conditionList = conditionList;
return (Criteria) this;
}
/**
* @param orderByClause 排序字段
*/
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
/**
* @param distinct 是否相异
*/
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public void setCondition(Map<String, Object> condition) {
this.condition = condition;
}
public Map<String, Object> getCondition() {
return condition;
}
/**
* @param mysqlOffset 指定返回记录行的偏移量<br>
* mysqlOffset= 5,mysqlLength=10; // 检索记录行 6-15
*/
public void setMysqlOffset(Integer mysqlOffset) {
this.mysqlOffset = mysqlOffset;
}
/**
* @param mysqlLength 指定返回记录行的最大数目<br>
* mysqlOffset= 5,mysqlLength=10; // 检索记录行 6-15
*/
public void setMysqlLength(Integer mysqlLength) {
this.mysqlLength = mysqlLength;
}
public Map<String, Object> getTargetColums() {
return targetColums;
}
public void removeTargetColums(String key) {
if (targetColums.containsKey(key)) {
targetColums.remove(key);
}
}
public void removeCondition(String key) {
if (condition.containsKey(key)) {
condition.remove(key);
}
}
public Object deepClone() throws IOException, ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
5.拦截器
这里用一个简单的拦截器来实现我们所需要的访问网址既是主页的功能,很明显现在这个逻辑是不全的,以后会慢慢完善它
package cn.yzstu.baldwinblog.filter;
import cn.yzstu.baldwinblog.bean.User;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* \* Created with IntelliJ IDEA.
* \* User: Baldwin
* \* E_Mail: [email protected] || [email protected]
* \* Date: 2019/12/20
* \* Time: 16:37
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class WebIntercepter extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("loginUser");
if (null == user) {
response.sendRedirect(request.getContextPath() + "/login/index.jsp");
return false;
}
return true;
}
}
写完拦截器之后还需要在启动文件中引入
@SpringBootApplication
@EnableCaching
@MapperScan("cn.yzstu.baldwinblog.mapper")
@ComponentScan(basePackages = {"cn.yzstu.common", "cn.yzstu.baldwinblog"})
public class BaldwinblogApplication extends WebMvcConfigurerAdapter {
@Autowired
private LoginInterceptor loginInterceptor;
public static void main(String[] args) {
SpringApplication.run(BaldwinblogApplication.class, args);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
excludePath.add("/css/**");
excludePath.add("/font/**");
excludePath.add("/font-awesome/**");
excludePath.add("/image/**");
excludePath.add("/js/**");
excludePath.add("/layui/**");
excludePath.add("/error");
registry.addInterceptor(new WebIntercepter()).addPathPatterns("/").excludePathPatterns(excludePath);
}
}
三、测试
直接运行项目,输入http://localhost:8080
输入账号登录
成功
四、总结
过程中遇到了一个问题,就是在验证一个ArrayList是否是空的时候不能用ArrayList==null来验证,应该是arrayList.size==0,因为ArrayList初始化的时候其实是初始化了一个size为0的ArrayList。
上一篇:从零开始,SpringBoot+Redis+MySQL搭建个人博客(五)-----添加注册功能并依托Redis实现邮箱限时验证注册