做农家乐网站,站内推广的方法和工具,制作单页网站,大学生创意电子产品设计传送门
JAVA8-lambda表达式1#xff1a;什么是lambda表达式
JAVA8-lambda表达式2#xff1a;常用的集合类api
JAVA8-lambda表达式3#xff1a;并行流#xff0c;提升效率的利器#xff1f;
JAVA8-lambda表达式4#xff1a;Optional用法
java8-lambda表达式5#xf…传送门
JAVA8-lambda表达式1什么是lambda表达式
JAVA8-lambda表达式2常用的集合类api
JAVA8-lambda表达式3并行流提升效率的利器
JAVA8-lambda表达式4Optional用法
java8-lambda表达式5toMap引发的线上故障
JAVA8-lambda表达式6重构和定制收集器
JAVA8-lambda表达式7重要的函数接口
如何看待写代码这件事
最近在公司写代码包括看代码突然有一点小小的感叹。好多人整天研究什么高并发高可用分布式开口架构闭口新技术就是不愿意花时间把自己的JAVA代码写的好一点。
把代码写好就是给自己印的最好的名片也是对同事最大的负责
可惜好多人不这样认为或者说可能是现在环境就是这样吧面试各种的造火箭考算法导致从业者只能投其所好刷题/刷各种高大上的所谓架构技术而忽视一个最本质的前提
那就是技术是为业务服务的绝大部分的公司是用不上所谓的大厂架构的强行匹配只会适得其反。
有空还是多琢磨琢磨怎么把那点JAVA代码写的更好吧。
这里的说法有点属于夹带私货了太过片面了切勿对号入座。
什么是模板方法
在很早以前真的是很早了看了下发布日期是2018年2月学习过模板方法它属于常用的设计中的一种。当时里面介绍的例子取自《Head First设计模式》所以文章算作是翻译过来的。例子比较简单实现也是用的继承多态的。而还有一种很常用的模板方法就是一个类静态方法使用者直接通过静态方法来调用
Template.execute(a,b);
Template为类名execute为方法a,b为参数
在上面的调用中Template.execute是不会变化顾名思义就是模板方法的意思。而ab则是需要调用方传递的参数必须是模板规定的类型。下面就以一个实际场景来看看如何抽象一个模板方法。
接口调用场景
对于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;}
在类上打上注解RestController或Controller现在一般自动转换json就用RestController在方法上打上注解RequestMapping或GetMapping/PostMapping等表示这个是一个接口方法在方法里面打上注解RequestParam或PathVariable用来获取参数
大致按照这3个步骤来操作剩下的主要就是业务代码编写了实际项目里面也没有什么大的区别。一般项目会分层简单的就三层Web/Service/Dao。
Web表示展示层接口的入参获取参数检验日志打印响应转换/返回包括异常处理Service就是业务层处理业务逻辑的是方法的主体代码Dao层称为存储层一般表示db处理也可以是其它持久操作
模板方法
根据上面简单三层的理解定义一个模板方法出来
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;}
}
这里定义了模板方法的步骤
入参类型如果是上面的例子只能的String肯定有局限性最好支持泛型比如都继承Request基类参数打印将参数都打印出来方便统计排查参数检验对输入参数进行检验如果不符合条件则抛出异常让步骤4异常来统一处理业务方法执行对于这种业务方法的执行可以定义一个接口让调用方来实现异常执行异常可以分为业务/全局异常进行统一的处理直接抛出或转换成对应异常码组装响应响应可以自定义比如如上的异常码/异常信息后置处理可以在方法结束时进行需要的后置处理比如打印日志方便后续监控
由此可见一个完整模板方法类似如下
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 T* param R*/public static T extends BaseRequestDTO, R extends BaseResponseDTO 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 BaseResponseDTOT
{/** 错误码 */private String code;/** 错误信息 */private String msg;/** 返回内容 */private T data;
}/*** 模板处理接口* * param T*/
public interface ServiceCallbackT
{void check(T req);void doService(T req);
}
至此模板方法已经初具雏形对于调用方来说即可如下
WebTemplate.execute(req, new BaseResponseDTO(), new ServiceCallback() {Overridepublic void check(Object req) {// 参数检验}Overridepublic void doService(Object req) {// 业务方法}}); lambda在模板方法中的应用
既然是要用lambda表达式在模板方法中应用所以就不能像刚才那样对于回调函数直接用匿名类这里就改造一下
/*** 模板回调函数* * param T*/
FunctionalInterface
public interface ServiceCallbackT
{default void check(T req){}void doService(T req);
}WebTemplate.execute(req, new BaseResponseDTO(), request - {});首先改造一下回调函数增加FunctionalInterface注解表示这是一个函数式接口将chec()方法声明为default这里java8的默认方法最近用lambda实现业务处理逻辑