5.SSM框架整合

5.SSM框架整合,第1张

5.SSM框架整合 5.SSM框架整合

ssm:spring+spring mvc+mybatis

5.1 整合的场所:web.xml

通过监听器配置mybatis,通过servlet配置mvc。

web.xml:


  
    Archetype Created Web Application

    
    
    
    
        contextConfigLocation
        
        classpath:spring-mybatis.xml
    

    
    
        org.springframework.web.context.ContextLoaderListener
    

    
    
    
        dispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            
            classpath:spring-mvc.xml
        
        1
    

    
        dispatcherServlet
        /
    

    
    
        encodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
            
            encoding
            UTF-8
        
        
            
            forceEncoding
            true
        
    
    
        encodingFilter
        /*
    

5.2 mvc和mybatis的配置文件: 5.2.1 spring-mvc.xml:( resources文件夹下)


    
    

    
    
        
        
    
    
    
    
    
    
    
        
        
            
                text/html;charset=UTF-8
                application/json;charset=UTF-8
            
        
    
    
    
    
        
        
            
            
        
    
    
    

5.2.2 spring-mybatis.xml:( resources文件夹下)


    
    

    
    
        
        
        
        
    
    
    
        
        
        
        
        
        
        
        
            
                
                
            
        
        
        
            
                
            
        
    
    
    
        
        
        
        
    
    
    
        
        
    
    
    
    
    
    

5.3 拦截器配置 5.3.1 HandlerInterceptor接口:
import org.springframework.web.servlet.HandlerInterceptor;
public interface HandlerInterceptor {
    
    //前置拦截,在控制器执行之前做事
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    //后置拦截,在控制器执行后做事
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    //在视图被渲染后做事
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}
5.3.2 拦截器应用

最常见的拦截器使用都是应用前置拦截,经常用作角色登录超时和权限验证。

5.3.2.1 登录超时

拦截器位于控制器之前,可以做对登录状态信息的验证功能,即在使用控制器方法之前,需要判断角色是否在登录状态。

这里将角色的信息存放在Session中,在拦截器中得到Session,进行角色信息判断。

public class TimeoutInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        String username = (String) session.getAttribute("username");
        if(username == null){
            //自己设置响应状态码,如400,401,402.....
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); //未授权
            PrintWriter pw = response.getWriter();
            pw.print("登录超时");
            pw.flush();
            pw.close();
            return false;
        }
        return true;
    }
}

需要单独在spring-mvc.xml配置文件中进行拦截器配置:


    
    
        
        
        
        
        
        
    
    

5.3.2.2 权限检测

控制器中的方法,不是任何角色都能够进行访问使用,所以需要进行角色的权限验证。这里提供有:

5.3.2.2.1 通过请求的url地址划分权限:

即在数据库中使用表的形式,存贮角色权限,权限对应url请求地址,改变角色权限时只需要改变数据库表即可。

1.最简单的权限验证方法是通过拦截器获取角色信息,再通过角色信息在使用业务层方法判断该角色是否有对应权限数据库中查询,

示例:

public class PermissionInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //拿到当前登录的用户名
        String username = (String) request.getSession().getAttribute("username");
        //获取当前访问的uri
        String uri = request.getRequestURI();
        //获取上下文路径,也可能是虚拟路径
        String contextPath = request.getContextPath();
        //访问的uri中需要将上下文路径去掉
        uri = uri.replace(contextPath, "");
        //去数据库查询当前登录用户是否具有访问该URL地址的权限
    	if(!userService.hasPermission(username, uri)){
            //自己设置响应状态码,如400,401,402.....
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); //未授权
            PrintWriter pw = response.getWriter();
            pw.print("权限不足,请联系管理员!");
            pw.flush();
            pw.close();
            return false;
        }
        return true;
    }
}

2.也可以在实体类中增加包含权限的属性信息,全部存储在Session中,然后进行权限验证,就避免了经常访问数据库。

比较简单,不做示例演示。

弊端:上述的这两种方式,能够在数据库中对每个用户进行精确的访问控制,但由于所有控制器中的url可能会很多,且每个角色都需要对应能够访问的所有url,数据库表会显得十分臃肿。

5.3.2.2.2 通过注解划分权限等级:

为了解决以上的弊端,对所有角色进行划分角色等级,如admin(管理员权限),user(普通用户权限),test(测试员权限)…等。

在控制器方法上使用注解标识所需要的权限,通过handler参数获取当前执行的方法,再获取方法上的注解参数,来获得对应方法执行所需要的权限。而用户角色的权限,依旧从数据库中得来,原理可以参照5.3.2.2.1的两种方式。
弊端:这种方式无法精确的对每一个角色进行访问控制,涉及到新增的权限以及更加精细的划分权限时,可能会需要更改代码。

定义的权限注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HashAuthority {
    //这个属性就是用来设置访问的角色
    String[] value() default {};
}

通过注解对控制器中的方法设置访问权限

@HashAuthority({"ADMIN","USER"})
@GetMapping("/search")
public Result search(UserCondition userCondition){
    
    return null;
}

@HashAuthority("TEST")
@GetMapping("/test")
public Result test(){
    
    return null;
}

拦截器代码:

public class PermissionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        //如果handler是一个方法的handler
        if(handler instanceof HandlerMethod){
            //获取拦截的方法
            Method method = ((HandlerMethod) handler).getMethod();
            HashAuthority authority = method.getAnnotation(HashAuthority.class);
            if(authority != null){
                //获取注解中设置的角色
                String[] roles = authority.value();
                HttpSession session = request.getSession();
                User user = (User) session.getAttribute("user");
                List userRoles = user.getRoles();
                boolean valid = Arrays.stream(roles).anyMatch(userRoles::contains);
                if(!valid){
                    response.setContentType("text/html;charset=UTF-8");
                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
                    PrintWriter writer = response.getWriter();
                    writer.print("权限不足,请联系管理员");
                    writer.flush();
                    writer.close();
                }
                return valid;
            }
        }
        return true;
    }
}

需要在spring-mvc.xml配置文件中进行拦截器配置(注:配置顺序决定拦截的顺序):


    
    
        
        
        
        
        
        
    
    
    
        
        
        
        
        
    

5.3.2.3 拦截器执行流程

拦截器与过滤器的区别:拦截器是在servlet中,控制器方法之前生效,而过滤器是在servlet之前生效。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5481582.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-12
下一篇2022-12-12

发表评论

登录后才能评论

评论列表(0条)

    保存