springMVC全局异常以及拦截器,过滤器不能拿到请求的方法

一、springMVC全局异常有点

         若有很多异常没有被包装,那么我们项目的类,包名,sql语句,数据库ip等关键信息都会暴露。

二、spring以及springMVC包扫描进行隔离。

         1.springMVC应该扫描controller,spring扫描其他bean

         2.coding:

spring配置文件:排除controller注解

       

springMVC配置文件:关闭默认扫描,只扫描controller注解

       

三、使用@Component注解

         1.默认控制层用@controller,服务层用@service,Dao层用@Repository,其他一律使用@Component。

四、ModelAndView

         不在作用于服务器转发就是跳转页面,使之返回Json对象,对异常进行重写包装。

五、SpringMVC全局异常流程图

         包装的异常即ModelAndView对象。

 

 

 

 

 

 

 

 

 

 

 

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.HandlerExceptionResolver;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

@Component

public class ExceptionResolver implements HandlerExceptionResolver{

         private static  final Logger log = LoggerFactory.getLogger(ExceptionResolver.class);

    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {

       //使用日志打印出异常

        log.error("{} Exception",httpServletRequest.getRequestURI(),e);

       //使用jackson封装异常

        ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());

        //使用jackson2.x的时候使用MappingJackson2JsonView,目前使用的是1.9。

        modelAndView.addObject("status",ResponseCode.ERROR.getCode());

        modelAndView.addObject("msg","接口异常,详情请查看服务端日志的异常信息");

        modelAndView.addObject("data",e.toString());

        return modelAndView;

    }

}

六、springMVC拦截器流程图

         1.拦截器配置

        

         /**表示所有路径及其子路径

         /*  表示当前路径,但不包括子路径

         /web项目的根目录请求

   

        

        

        

   

         2.拦截器执行流程

        

         3.重置HttpServletResponse

         4.解决拦截登陆循环问题

七、HandlerInterceptor(preHandler(),postHandler(),afterHandler())

PreHandler返回false那么不进入Controller,直接返回。返回true,跳到postHandler,最后调到afterHandler。

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        log.info("preHandle");

        //请求中Controller中的方法名

        HandlerMethod handlerMethod = (HandlerMethod)handler;

        //解析HandlerMethod

        String methodName = handlerMethod.getMethod().getName();

        String className = handlerMethod.getBean().getClass().getSimpleName();

        //解析参数,具体的参数key以及value是什么,我们打印日志

        StringBuffer requestParamBuffer = new StringBuffer();

        Map paramMap = request.getParameterMap();

        Iterator it = paramMap.entrySet().iterator();

        while (it.hasNext()){

            Map.Entry entry = (Map.Entry)it.next();

            String mapKey = (String)entry.getKey();

            String mapValue = StringUtils.EMPTY;

            //request这个参数的map,里面的value返回的是一个String[]

            Object obj = entry.getValue();

            if(obj instanceof String[]){

                String[] strs = (String[])obj;

                mapValue = Arrays.toString(strs);

            }

            requestParamBuffer.append(mapKey).append("=").append(mapValue);

        }

 

        if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){

            log.info("权限拦截器拦截到请求,className:{},methodName:{}",className,methodName);

            //如果是拦截到登录请求,不打印参数,因为参数里面有密码,全部会打印到日志中,防止日志泄露

            return true;

        }

        log.info("权限拦截器拦截到请求,className:{},methodName:{},param:{}",className,methodName,requestParamBuffer.toString());

        User user = null;

        String loginToken = CookieUtil.readLoginToken(request);

        if(StringUtils.isNotEmpty(loginToken)){

            String userJsonStr = RedisShardedPoolUtil.get(loginToken);

            user = JsonUtil.string2Obj(userJsonStr,User.class);

        }

        if(user == null || (user.getRole().intValue() != Const.Role.ROLE_ADMIN)){

            //返回false.即不会调用controller里的方法

            response.reset();//这里要添加reset,否则报异常 getWriter() has already been called for this response.

            response.setCharacterEncoding("UTF-8");//geelynote 这里要设置编码,否则会乱码

            response.setContentType("application/json;charset=UTF-8");//geelynote 这里要设置返回值的类型,因为全部是json接口。

            PrintWriter out = response.getWriter();

            out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("拦截器拦截,用户无权限操作")));

            out.flush();

            out.close();//geelynote 这里要关闭

            return false;

        }

        return true;

    }

你可能感兴趣的:(java)