JAVA8-lambda表达式1:什么是lambda表达式
JAVA8-lambda表达式2:常用的集合类api
JAVA8-lambda表达式3:并行流,提升效率的利器?
JAVA8-lambda表达式4:Optional用法
java8-lambda表达式5:toMap引发的线上故障
JAVA8-lambda表达式6:重构和定制收集器
JAVA8-lambda表达式7:重要的函数接口
最近在公司写代码(包括看代码),突然有一点小小的感叹。好多人整天研究什么高并发,高可用,分布式,开口架构闭口新技术,就是不愿意花时间把自己的JAVA代码写的好一点。
把代码写好就是给自己印的最好的名片,也是对同事最大的负责!
可惜好多人不这样认为,或者说可能是现在环境就是这样吧:面试各种的造火箭,考算法导致从业者只能投其所好,刷题/刷各种高大上的所谓架构技术,而忽视一个最本质的前提!
那就是技术是为业务服务的,绝大部分的公司是用不上所谓的大厂架构的,强行匹配只会适得其反。
有空还是多琢磨琢磨怎么把那点JAVA代码写的更好吧。
这里的说法有点属于"夹带私货"了,太过片面了,切勿对号入座。
在很早以前(真的是很早了,看了下发布日期是2018年2月!),学习过模板方法,它属于常用的设计中的一种。当时里面介绍的例子取自《Head First设计模式》,所以文章算作是翻译过来的。例子比较简单,实现也是用的继承+多态的。而还有一种很常用的模板方法,就是一个类+静态方法,使用者直接通过静态方法来调用!
Template.execute(a,b);
在上面的调用中,Template.execute是不会变化,顾名思义就是模板方法的意思。而a,b则是需要调用方传递的参数,必须是模板规定的类型。下面就以一个实际场景来看看如何抽象一个模板方法。
对于JAVA程序员来说,spring肯定绕不开的结。当需要写一个后端接口的时候,通过springMVC可以很方便的来实现,比如在Oauth2系列7:授权码和访问令牌的颁发流程是怎样实现的?里面提到的准备工作-验证基本信息:
@RestController
@RequestMapping("/auth")
public class OauthController
{
@GetMapping("/authorize")
public void authorize(@RequestParam("response_type") String responseType, @RequestParam("client_id") String clientId,
@RequestParam("redirect_uri") String redirectUri, String scope)
{
}
}
还有验证客户端-生成访问令牌:
@PostMapping("/token")
public TokenModel getToken(@RequestBody GetTokenRequest getTokenRequest) {
// 获取令牌前置检验
preGetTokenCheck(getTokenRequest);
// 检验授权码
checkCode(getTokenRequest.getCode());
// 生成t访问令牌
TokenModel tokenModel = generateToken();
return tokenModel;
}
private TokenModel generateToken() {
// 获取code信息,比如从redis
// CodeModel codeModel = getCode;
TokenModel tokenModel = new TokenModel();
tokenModel.setAccessToken(UUID.randomUUID().toString());
tokenModel.setExpiresIn(3600);
tokenModel.setRefreshToken(UUID.randomUUID().toString());
// tokenModel.setScope(codeModel.getScope);
return tokenModel;
}
大致按照这3个步骤来操作,剩下的主要就是业务代码编写了(实际项目里面也没有什么大的区别)。一般项目会分层,简单的就三层:Web/Service/Dao。
根据上面简单三层的理解,定义一个模板方法出来:
@Slf4j
public class WebTemplate
{
public static String execute(String req)
{
try
{
// 1:打印入参
log.info("方法参数:{}", req);
// 2:参数检验
// TODO
// 3:业务方法
}
catch (Exception e)
{
// 4:异常处理
return "fail";
}
return "success";
}
}
这里定义了模板方法的步骤:
由此可见一个完整模板方法类似如下:
package com.tw.tsm.base.template;
import com.tw.tsm.base.request.BaseRequestDTO;
import com.tw.tsm.base.response.BaseResponseDTO;
import lombok.extern.slf4j.Slf4j;
/**
* 模板方法类
*/
@Slf4j
public class WebTemplate
{
/**
* 模板方法
* @param req 请求参数
* @param res 响应参数
* @param callback 回调方法
* @param
* @param
*/
public static void execute(T req, R res, ServiceCallback callback)
{
try
{
// 1:打印入参
log.info("方法参数:{}", req);
// 2:参数检验
callback.check(req);
// 3:业务方法
callback.doService(req);
}
catch (Exception e)
{
// 4:异常处理
}
finally
{
log.info("处理结果:{}", res);
}
}
}
/**
* 请求基类
*/
public class BaseRequestDTO
{
}
/**
* 响应基类
*/
@Data
public class BaseResponseDTO
{
/** 错误码 */
private String code;
/** 错误信息 */
private String msg;
/** 返回内容 */
private T data;
}
/**
* 模板处理接口
*
* @param
*/
public interface ServiceCallback
{
void check(T req);
void doService(T req);
}
至此,模板方法已经初具雏形,对于调用方来说,即可如下:
WebTemplate.execute(req, new BaseResponseDTO(), new ServiceCallback() {
@Override
public void check(Object req) {
// 参数检验
}
@Override
public void doService(Object req) {
// 业务方法
}
});
既然是要用lambda表达式在模板方法中应用,所以就不能像刚才那样对于回调函数直接用匿名类,这里就改造一下:
/**
* 模板回调函数
*
* @param
*/
@FunctionalInterface
public interface ServiceCallback
{
default void check(T req)
{
}
void doService(T req);
}
WebTemplate.execute(req, new BaseResponseDTO(), request -> {
});