Spring MVC拦截器

使用场景

记录web请求的相关日志,可以做信息监控,统计,分析
检查web的访问权限,例如发现用户没有登录后,重定向到登录页面。
打开关闭数据库连接–预处理打开,后处理关闭,可以避免所有的业务方法中都编写相似的类。

Spring MVC的请求流程

Spring-MVC请求流程

HandlerInterceptor接口

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception;
void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception;
void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) throws Exception;
}

1.preHandle():预处理回调方法,若方法返回值为true,请求继续(调用下一个拦截器或处理器方法);若方法返回值为false,请求处理流程中断,不会继续调用其他的拦截器或处理器方法,此时需要通过response产生响应;
2.postHandle():后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时可以通过modelAndView对模型数据进行处理或对视图进行处理
3.afterCompletion():整个请求处理完毕回调方法,即在视图渲染完毕时调用

实例:用户登录检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
if (request.getSession().getAttribute(Constants.USER_SESSION_ATTR) != null) {
return true;
}
response.sendRedirect("/");
return false;
}
}

配置Interceptor

1
2
3
4
5
6
7
8
9
10
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/account/*").excludePathPatterns("/");
}
}

codis 配置

@Configuration
public class CodisConfiguration {
@Value(“${codis.zookeeper.clients}”)
private String zkClients;
@Value(“${codis.zookeeper.proxyDir}”)
private String zkDir;
@Value(“${codis.poolConfig.maxIdle}”)
private int maxIdle;
@Value(“${codis.poolConfig.maxTotal}”)
private int maxTotal;

@Bean
public JedisResourcePool jedisResourcePool() {
    JedisPoolConfig poolConfig = new JedisPoolConfig();
    poolConfig.setMaxIdle(maxIdle);
    poolConfig.setMaxTotal(maxTotal);
    poolConfig.setTestOnBorrow(true);
    return RoundRobinJedisPool.create().curatorClient(zkClients, 30000).zkProxyDir(zkDir)
            .poolConfig(poolConfig).build();
}

}

二叉树的遍历

中序遍历

从树的根节点开始,沿着其左孩子域向下移动,直到某一节点再无左节点,访问这个最左边的节点,接下来再从此节点的右孩子
开始进行中序遍历,当右子树遍历完了以后,退回到上一层的未访问节点继续二叉树遍历,直到书中所有节点被访问到为止。

先序遍历

对节点的访问时在其左、右子树之前进行的。遍历是从根节点开始的,遇到每个节点时,遍历过程为:
访问根节点
先序遍历其左子树
先序遍历其右子树

使用Heroku免费部署Java应用

简介

Heroku是一个支持多种编程语言的云平台即服务。

准备

1.注册Herku账号
2.在本地安装Java8
3.在本地安装Maven3

安装

安装本地客户端 Heroku-cli,安装Heroku-cli

然后打开命令行工具登录如:

1
2
3
4
>heroku login
Enter your Heroku credentials.
Email: email@example.com
Password:

部署应用

这里我们使用官网给的应用
首先克隆git clone https://github.com/heroku/java-getting-started.git
cd到项目目录: cd java-getting-started
创建应用到Heroku上如:

1
2
3
> heroku create
Creating shielded-caverns-88393... done, stack is cedar-14
http://shielded-caverns-88393.herokuapp.com/ | https://git.heroku.com/shielded-caverns-88393.git

shielded-caverns-88393 这是一个随机的数,可以到keroku的应用列表找到这个应用,然后去修改。

部署应用代码

git push heroku master

访问

heroku open

查看日志

1
2
3
4
5
6
D:\resource\java-getting-started>heroku logs --tail
2016-08-29T02:37:19.738508+00:00 heroku[api]: Release v2 created by yang993505@gmail.com
2016-08-29T02:37:19.738508+00:00 heroku[api]: Enable Logplex by yang993505@gmail.com
2016-08-29T02:37:45.907720+00:00 heroku[router]: at=info code=H81 desc="Blank app" method=GET path="/" h
erns-88393.herokuapp.com request_id=9872849a-d62c-4053-b744-b067e1270c3b fwd="45.55.27.82" dyno= connect
s=502 bytes=

定义Procfile

1
web: java -jar target/helloworld.jar

本地运行

安装依赖

mvn clean install

运行

heroku local web
打开浏览器输入localhost:5000即可访问

其他服务提供

默认情况下,Heroku能够显示1500行日志。然而,它提供完整的日志流作为服务——和几个插件提供商所写的日志服务,
提供诸如日志持久性、搜索和电子邮件和短信提醒。

下面,我们将提供一个日志插件,Papertrail。

1
2
3
4
D:\resource\java-getting-started>heroku addons:create papertrail
Creating papertrail on shielded-caverns-88393... !
! Please verify your account to install this add-on plan (please enter a credit card) For more information, see
! https://devcenter.heroku.com/categories/billing Verify now at https://heroku.com/verify

这里提示要在heroku输入一个银行卡的信息。先不做这个演示了

使用heroku addons可以查看已经装好的插件服务。

heroku终端

heroku run bash

设置变量

heroku config:set ENERGY=”20 GeV”
查看变量
heroku config

使用数据库

数据库的使用也是需要安装服务的,详情见
安装数据库插件

Spring Boot 中的统一异常处理

Spring Boot中默认带了error的映射,但是这个错误页面显示给用户并不是很友好。

统一异常处理

通过使用@ControllerAdvice定义统一异常处理的类,而不是在每个Controller中逐个定义。

@ExceptionHandler用来定义函数针对的函数类型,最后将Exception对象和请求URL映射到URL中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@ControllerAdvice
class ExceptionTranslator {
public static final String DEFAULT_ERROR_VIEW = "error";
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}

实现error.html页面展示

在templates目录下创建error.html。
例如:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title>统一异常处理</title>
</head>
<body>
<h1>Error Handler</h1>
<div th:text="${url}"></div>
<div th:text="${exception.message}"></div>
</body>
</html>

返回使用Json格式

只需在@ExceptionHandler之后加入@ResponseBody,就能让处理函数return的内容转换为JSON格式

创建一个JSON返回对象,如:

1
2
3
4
5
6
7
8
9
10
11
public class ErrorDTO implements Serializable {
private static final long serialVersionUID = 1L;
private final String message;
private final String description;
private List<FieldErrorDTO> fieldErrors;
//getter和setter省略
}

可以为指定的Exception添加异常处理

1
2
3
4
5
6
@ExceptionHandler(ConcurrencyFailureException.class)
@ResponseStatus(HttpStatus.CONFLICT)
@ResponseBody
public ErrorDTO processConcurencyError(ConcurrencyFailureException ex) {
return new ErrorDTO(ErrorConstants.ERR_CONCURRENCY_FAILURE);
}

ErrorConstants.ERR_CONCURRENCY_FAILURE 是定义的一个异常信息。