日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java代码】反射机制处理传递给mapper文件的非Map类型参数对象(指定属性为空则设置默认值)

發布時間:2024/10/6 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java代码】反射机制处理传递给mapper文件的非Map类型参数对象(指定属性为空则设置默认值) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. why

為什么要攔截傳遞給 mapper 文件的參數對象呢?因為要對指定屬性設置默認值。如何攔截傳遞給 mapper 文件的參數對象可以參考《使用(org.apache.ibatis.plugin.Interceptor)攔截器實現全局參數注入》這里我們只貼出處理攔截對象的核心方法。

2. code

既然是核心方法,無關的@Override方法不再貼出, 參數對象是Map類型的不是重點,這里主要看一下封裝對象借助反射機制通過 getter 和 setter 方法獲取和設置指定屬性值的操作。

public class SchemaInterceptor implements Interceptor {/*** mapper.xml 使用SCHEMA時的參數名稱*/private static final String SCHEMA = "schemaName";/*** 設置默認的schema*/private String schema = "public";/*** 攔截到的動態SQL*/private Set<Integer> sourceStorage = new HashSet<>();@Overridepublic Object intercept(Invocation invocation) throws Throwable {Object[] args = invocation.getArgs();MappedStatement mappedStatement = (MappedStatement) args[0];SqlSource sqlSource = mappedStatement.getSqlSource();// 只攔截動態SQLif (sqlSource instanceof DynamicSqlSource) {// 獲取到sqlNode對象Field field = DynamicSqlSource.class.getDeclaredField("rootSqlNode");field.setAccessible(true);SqlNode sqlNode = (SqlNode) field.get(sqlSource);Object argParameter = args[1];// 獲取傳遞給 mapper 的參數對象if (!sourceStorage.contains(sqlSource.hashCode()) && argParameter != null) {if (argParameter instanceof HashMap) {// 處理 map 類型的參數Map<String, Object> argMap = (Map<String, Object>) argParameter;// 判斷是否傳遞 schemaName或schema 如果已經傳遞則使用用戶傳遞的值 否則使用默認值String schemaNameStr = "schemaName", schemaStr = "schema";if (StringUtils.isEmpty(MapUtils.getString(argMap, schemaNameStr)) && StringUtils.isEmpty(MapUtils.getString(argMap, schemaStr))) {SqlNode proxyNode = proxyNode(sqlNode);field.set(sqlSource, proxyNode);}} else {// 處理封裝成請求對象類型的參數Class<?> clz = argParameter.getClass();// 獲取實體類的所有屬性Field[] fields = clz.getDeclaredFields();for (Field f : fields) {String fieldName = f.getName();Class<?> fieldType = f.getType();// 處理 schemaName 屬性if (SCHEMA.equals(fieldName)) {// 獲取 schemaName 屬性的 getter 方法String methodName = getMethodName(fieldName);String getName = "get" + methodName;Method getFieldValue = clz.getMethod(getName);String val = (String) getFieldValue.invoke(argParameter);// schemaName 屬性值為空則使用默認值if (StringUtils.isBlank(val)) {String setName = "set" + methodName;Method setFieldValue = clz.getMethod(setName, fieldType);setFieldValue.invoke(argParameter, schema);}}}}sourceStorage.add(sqlSource.hashCode());}}return invocation.proceed();}/*** 通過動態代理對象 添加schema參數** @param sqlNode SQL節點* @return SqlNode*/private SqlNode proxyNode(SqlNode sqlNode) {return (SqlNode) Proxy.newProxyInstance(sqlNode.getClass().getClassLoader(),new Class[]{SqlNode.class}, new SqlNodeInvocationHandler(sqlNode));}private class SqlNodeInvocationHandler implements InvocationHandler {private SqlNode target;SqlNodeInvocationHandler(SqlNode target) {super();this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {DynamicContext context = (DynamicContext) args[0];setSchema(schema);context.getBindings().put(SCHEMA, schema);return method.invoke(target, args);}}/*** 給schema 添加.** @param schema schemaName*/private void setSchema(String schema) {String pointStr = ".";if (StringUtils.isNotBlank(schema)) {if (!schema.endsWith(pointStr)) {schema += pointStr;}}this.schema = schema;}/*** 將首字母變成大寫** @param fieldName 字段名稱* @return 首字母大寫的字段名稱*/private static String getMethodName(String fieldName) {byte[] items = fieldName.getBytes();items[0] = (byte) ((char) items[0] - 'a' + 'A');return new String(items);}

方法解析

攔截到的參數對象是 Object 類型,可以通過方法名獲取其 getter 和 setter 方法,使用獲取到的方法執行即可獲取或設置指定的屬性值:

Object argParameter = args[1];// 處理封裝成請求對象類型的參數Class<?> clz = argParameter.getClass();// 獲取實體類的所有屬性Field[] fields = clz.getDeclaredFields();for (Field f : fields) {// 屬性的名稱String fieldName = f.getName();// 屬性的類型Class<?> fieldType = f.getType();// 處理 schemaName 屬性if (SCHEMA.equals(fieldName)) {// 獲取 schemaName 屬性的 getter 方法String methodName = getMethodName(fieldName);// 方法名String getName = "get" + methodName;// 獲取到的 getter 方法Method getFieldValue = clz.getMethod("get" + methodName);// 執行 getter 方法String val = (String) getFieldValue.invoke(argParameter);// schemaName 屬性值為空則使用默認值if (StringUtils.isBlank(val)) {// 方法名String setName = "set" + methodName;// 獲取 setter 方法 需要傳遞當前屬性的類型Method setFieldValue = clz.getMethod(setName, fieldType);// 執行 setter 方法setFieldValue.invoke(argParameter, schema);}}}

將首字母大寫:

/*** 將首字母變成大寫** @param fieldName 字段名稱【字段的第一位必須是小寫的字母】* @return 首字母大寫的字段名稱*/private static String getMethodName(String fieldName) {byte[] items = fieldName.getBytes();items[0] = (byte) ((char) items[0] - 'a' + 'A');return new String(items);}

總結

以上是生活随笔為你收集整理的【Java代码】反射机制处理传递给mapper文件的非Map类型参数对象(指定属性为空则设置默认值)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。