Today Study 20190530

Posted by nobt Blog on May 30, 2019

@ControllerAdvice 是什么

在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。参考:@ControllerAdvice 文档

常见用法

一般项目都会定义一个类似于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@ControllerAdvice
public class GlobalExceptionHandler {

    protected Logger logger =  LoggerFactory.getLogger(this.getClass());

    public static final String DEFAULT_ERROR_VIEW = "error";

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(Exception e, HttpServletRequest request) throws Exception {
        logger.info("请求地址:" + request.getRequestURL());
        ModelAndView mav = new ModelAndView();
        logger.error("异常信息:",e);
        mav.setViewName(DEFAULT_ERROR_VIEW);
        return mav;
    }
}

全局异常处理,统一处理controller中发生的异常

@ExceptionHandler(value = Exception.class)中的value异常类型可以自定义,比如:

1
2
3
4
5
6
7
8
9
10
11
12
public class MyException extends RuntimeException {

    public MyException(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    private String code;
    private String msg;

    // getter & setter
}

然后修改value如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@ControllerAdvice
public class MyExceptionHandler {

	/**
     * 拦截捕捉自定义异常 MyException.class
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MyException.class)
    public Map myErrorHandler(MyException ex) {
        Map map = new HashMap();
        map.put("code", ex.getCode());
        map.put("msg", ex.getMsg());
        return map;
    }

}

测试的话,编写好@ControllerAdvice类后,在controller中throw一个Exception

1
2
3
4
5
6
7
8
9
@RestController
public class TestController {
	
	@RequestMapping("/test")
	public String test(){
		throw new MyException(10000, "system error.");
	}

}

访问该controller就会返回自定义的异常json信息

注意

@ControllerAdvice可以通过在方法上增加@ResponseBody注解放回json,也可以直接使用注解@RestControllerAdvice免去注解@ResponseBody

以上至介绍了统一处理异常机制@ExceptionHandler,在@ControllerAdvice中还可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	**
     * 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {}

    /**
     * 把值绑定到Model中,使全局@RequestMapping可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("author", "Magical Sam");
    }

数据结构和算法的关系

数据结构是偏系统底层的概念,而算法是偏应用层的概念,算法操作数据结构

常见的数据结构链表、数组

链表:不连续的内存空间,通过指针连接元素

数组:连续的内存空间,元素有序依次存储

由于数组是有序的,所以数组查询快,增删慢(增加、删除节点需要移动其它元素,复杂度高)

链表由于指针的特性增加删除快而简单,查询慢(由于无序,查询需要遍历元素)

spring boot中如何自定义过滤器Filter

自定义过滤器,Object implements Filter的类还是要写,只是在spring boot中去掉web.xml后的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class WebConfiguration  {
	
    @Bean
    public FilterRegistrationBean filterRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new SecurityFilter());
        registration.addUrlPatterns("/*");
        registration.addInitParameter("paramName", "paramValue");
        registration.setName("MyFilter");
        registration.setOrder(1);
        return registration;
    }
 
}

回顾一下老写法,在web.xml中配置自定义过滤器如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<filter>
	<filter-name>MyFilter</filter-name>
	<filter-class>com.nobt.MyFilter</filter-class>
	<init-param>
		<param-name>EXCEPTION_URI</param-name>
		<param-value>login.html,*.js</param-value>
	</init-param>
	<init-param>
		<param-name>ERR_URL</param-name>
		<param-value>login.html</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>MyFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

总结新用法:

  • 实现javax.servlet.Filter接口,实现Filter方法
  • 添加 @Configuration 注解,将自定义Filter加入过滤链

缺陷:

  • 队列(mq)、缓存(redis)、搜索引擎(es)、分布式(spring cloud)的具体实现

    队列只是简单的了解到比如点对点queue、群发topic

    redis了解程度仅限于常用crud,其中细节的多数据类型、持久化、结合实际业务用redis达到高效率的做法等了解有限

    搜索引擎只简单看过lucene

    springcloud只简单的动手过如eureka、config、hystrix、feign、zuul,将服务提供者和服务消费者分模块建立,并分开部署启动后注册到eureka,通过feign远程调用,config动态拉取远端github配置并生效,hystrix达到服务降级/处理服务异常超时等问题,zuul控制微服务网关统一管理

    谈谈项目分模块的理解:

    单体的项目也可以通过meven分模块建立,分模块后的模块引用就类似于单独开发出来的jar包被引用,最终达到的效果与传统项目(所有服务、工具都在一个项目)效果一致,实际上也是统一部署,只是涉及到jar包的引用,通过maven最终打包出来一个jar/war包供启动,但是当项目复杂时可降低复杂度,更清晰的开发与维护,像spring cloud/dubbo微服务概念中,比如一个服务提供者和服务消费者在代码层面就是分模块,并部署也是分开部署的,他们之间的调用通过注册中心维护关系,并远程调用

  • springboot中一些细节的配置方式,没经验/对springboot的不熟悉可能导致愚蠢的做法