发表于: 2020-02-11 22:55:13
1 1400
今天完成的事:
1、设置拦截器,判断用户是否被冻结。
原本是想直接在拦截器中获取request的参数,顶多识别一下传入的用户id参数名称,看看是id,还是uid,然后根据id查询对应的用户状态是冻结还是解冻。
但是因为传递的参数是application/json,我看网上说这种不能使用 request.getParameter() 方法,要通过获取 流 的形式,截取参数,因为只能读取一次好像。。还需要截取后再将流放到request中,由接口调用。。太麻烦了,但是这样就可修改字符串中的“+”了,应该也可以直接在拦截器中解密参数吧。。有待考证。。
目前就是使用session,存储用户id,因为小程序没有cookie嘛,在拦截器中获取该session,然后根据id查询该用户的状态。
设置session过期时间为5分钟,在不访问的时候,5分钟后就无法访问,如果一直在访问,那么距第一次登陆访问超过5分钟也没事。
也就是说,过期时间是最后一次访问和下一次访问的间隔时间。
在复盘服务器上的项目,过期时间设置为12个小时。
在SSM中,配置拦截器需要在springmvc.xml中配置,如下图,设置拦截、放行的url,并指向bean的类,然后设置 interceptor 类。
springboot中,添加 interceptor 类,纳入spring管理,重写各个方法。然后设置配置类 WebMvcConfigurer 类,实现 WebMvcConfigurer 类,来注册、添加拦截器。
拦截判断用户若是冻结状态,则重定向到指定接口,返回冻结状态码。注意不要写成拦截范围内的url。。
只有在用户状态为解冻时,才会通过拦截,也就是说,如果没有登录,就没有userid的session,获取不了session,查不了用户数据,也算是被拦截。
interceptor 类,实现 HandlerInterceptor 类。
package com.dxz.home.interceptor;
import com.dxz.home.dao.UserMapper;
import com.dxz.home.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Component
public class UserInterceptor implements HandlerInterceptor {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Resource
UserMapper userMapper;
// 拦截器最先被执行的方法,也可以当做是对当前请求的预处理。
// 返回true时,会继续调用下一个拦截器的preHandle方法,
// 如果是最后一个拦截器就调用当前请求的controller方法。
// 返回false时,表示请求结束,后续拦截器和controller方法都不会执行,可以重定向到指定页面。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
// 这里的 userId 是登陆时放入session的
Long userId = (Long) session.getAttribute("userId");
log.info("用户id {} 已获取",userId);
// String url = "http://" + request.getServerName() //服务器地址
// + ":"
// + request.getServerPort() //端口号
// + request.getContextPath() //项目名称
// + request.getServletPath() //请求页面或其他地址
// + "?" + (request.getQueryString()); //参数
// log.info("请求URL为:"+ url);
User user = null;
if(userId != null) {
user = userMapper.selectByPrimaryKey(userId);
if(user != null && user.getStatus() == 1){
log.info("用户id {} ,查询用户信息:{}",userId,user);
return true;
}
}
// 重定向到用户冻结接口
response.sendRedirect("/error");
return false;
}
// 在preHandle方法返回true时,当前请求被处理之后被调用,
// 但是会在前端控制器进行视图渲染之前被调用,可以对controller处理过的ModelAndView进行处理。
// 先声明的拦截器preHandle方法先执行,其postHandle方法是后执行。
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
// 在preHandle方法返回true时被调用,但是是在整个请求结束后,
// 视图已经渲染后,才执行,这个方法主要是进行资源清理工作。
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
WebConfigurer 类,实现 WebMvcConfigurer 类。
package com.dxz.home.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Autowired
private UserInterceptor userInterceptor;
// 这个方法是用来配置静态资源的,比如html,js,css,等等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns("/**") 表示拦截所有的请求,
// excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
registry.addInterceptor(userInterceptor).addPathPatterns("/b/**").excludePathPatterns("/**/login");
}
}
2、使用事务保持多个方法的一致性。
对于事务,最简单的理解就是,将多个方法操作绑定,保持一致性,要么都成功,要么就失败。
比如转账,需要从A账号减去一定金额,就需要在B账号增加一定金额,否则就没有一致性,那么整个转账的操作就是失败的。
对于这个的使用,需要考虑后一个方法如果执行失败,会不会对前一个方法造成影响,如果会,则需要添加事务,如果不会,那也不是每个包含多方法的方法都需要添加事务。
比如,前一个方法是查询,需要设置到后一个修改方法中,如果后一个方法失败,那么前一个方法还是查询过了,反而会因为事务的设置,而多了一个步骤。
如下,就只是事务的最简单实用,参考网址:http://www.pianshen.com/article/4055314134/
首先在springboot项目启动类上添加注解 @EnableTransactionManagement ,开启声明式事务。
然后在service实现类的方法上,添加 @Transactional 注解。
在该方法中,实现两个编辑积分的方法,在不添加“ int = 1/0 ”时,两个方法都实现了,添加了这个绝对异常后,如果不使用事务,就只有异常前的方法会实现,使用了事务后,两个方法都没有实现,就保持了一致性。
需要注意的是, @Transactional 注解要使用在具体的类、方法上,而且是 public 公开的。
3、修改参数校验逻辑。
因为和前端约定,查询时,不输入条件就是查询该条件的全部,所以这里就不能设置参数最小为1,而应该是0。
明天计划的事:
1、测试接口
遇到的问题:
无
收获:
1、设置拦截器,判断用户是否被冻结。
了解了SSM、springboot拦截器设置的区别。
2、使用事务保持多个方法的一致性。
对于事务,最简单的理解就是,将多个方法操作绑定,保持一致性,要么都成功,要么就失败。
事务的最简单实用,参考网址:http://www.pianshen.com/article/4055314134/
首先在springboot项目启动类上添加注解 @EnableTransactionManagement ,开启声明式事务。然后在service实现类的方法上,添加 @Transactional 注解。
3、修改参数校验逻辑。
评论