黄a在线观看-黄a在线-黄a大片-黄色片在线看-黄色毛片免费-黄色大片网站

您的位置:首頁技術文章
文章詳情頁

MyBatis攔截器的原理與使用

瀏覽:61日期:2023-10-19 09:07:07
目錄一、攔截對象和接口實現示例二、攔截器注冊的三種方式1.XML注冊2.配置類注冊3.注解方式三、ParameterHandler參數改寫-修改時間和修改人統一插入四、通過StatementHandler改寫SQL一、攔截對象和接口實現示例

MyBatis攔截器的作用是在于Dao到DB中間進行額外的處理。大部分情況下通過mybatis的xml配置sql都可以達到想要的DB操作效果,然而存在一些類似或者相同的查詢條件或者查詢要求,這些可以通過攔截器的實現可以提升開發效率,比如:分頁、插入和更新時間/人、數據權限、SQL監控日志等。

Mybatis支持四種對象攔截Executor、StatementHandler、PameterHandler和ResultSetHandler Executor:攔截執行器的方法。 StatementHandler:攔截Sql語法構建的處理。 ParameterHandler:攔截參數的處理。 ResultHandler:攔截結果集的處理。

public interface Executor { ResultHandler NO_RESULT_HANDLER = null; int update(MappedStatement var1, Object var2) throws SQLException; <E> List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, CacheKey var5, BoundSql var6) throws SQLException; <E> List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4) throws SQLException; <E> Cursor<E> queryCursor(MappedStatement var1, Object var2, RowBounds var3) throws SQLException; List<BatchResult> flushStatements() throws SQLException; void commit(boolean var1) throws SQLException; void rollback(boolean var1) throws SQLException; CacheKey createCacheKey(MappedStatement var1, Object var2, RowBounds var3, BoundSql var4); boolean isCached(MappedStatement var1, CacheKey var2); void clearLocalCache(); void deferLoad(MappedStatement var1, MetaObject var2, String var3, CacheKey var4, Class<?> var5); Transaction getTransaction(); void close(boolean var1); boolean isClosed(); void setExecutorWrapper(Executor var1);}public interface StatementHandler { Statement prepare(Connection var1, Integer var2) throws SQLException; void parameterize(Statement var1) throws SQLException; void batch(Statement var1) throws SQLException; int update(Statement var1) throws SQLException; <E> List<E> query(Statement var1, ResultHandler var2) throws SQLException; <E> Cursor<E> queryCursor(Statement var1) throws SQLException; BoundSql getBoundSql(); ParameterHandler getParameterHandler();}public interface ParameterHandler { Object getParameterObject(); void setParameters(PreparedStatement var1) throws SQLException;}public interface ResultHandler<T> { void handleResult(ResultContext<? extends T> var1);}

攔截的執行順序是Executor->StatementHandler->ParameterHandler->ResultHandler

MyBatis提供的攔截器接口:

public interface Interceptor { Object intercept(Invocation var1) throws Throwable; default Object plugin(Object target) {return Plugin.wrap(target, this); } default void setProperties(Properties properties) {}}

Object intercept方法用于攔截器的實現;

Object plugin方法用于判斷執行攔截器的類型;

void setProperties方法用于獲取配置項的屬性。

攔截對象和攔截器接口的結合,自定義的攔截器類需要實現攔截器接口,并通過注解@Intercepts和參數@Signature來聲明要攔截的對象。

@Signature參數type是攔截對象,method是攔截的方法,即上面的四個類對應的方法,args是攔截方法對應的參數(方法存在重載因此需要指明參數個數和類型)

@Intercepts可以有多個@Signature,即一個攔截器實現類可以同時攔截多個對象及方法,示例如下:

Executor->intercept StatementHandler->intercept ParameterHandler->intercept ResultHandler->intercept

@Intercepts({@Signature(type = Executor.class,method = 'query',args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class SelectPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {if (invocation.getTarget() instanceof Executor) { System.out.println('SelectPlugin');}return invocation.proceed(); } @Override public Object plugin(Object target) {if (target instanceof Executor) { return Plugin.wrap(target, this);}return target; } @Override public void setProperties(Properties properties) {}}@Intercepts({@Signature(type = StatementHandler.class, method = 'prepare', args = {Connection.class, Integer.class})})public class StatementPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {if (invocation.getTarget() instanceof StatementHandler) { System.out.println('StatementPlugin');}return invocation.proceed(); } @Override public Object plugin(Object target) {if (target instanceof StatementHandler) { return Plugin.wrap(target, this);}return target; } @Override public void setProperties(Properties properties) {}}@Intercepts({@Signature(type = ParameterHandler.class,method = 'setParameters',args = {PreparedStatement.class})})public class ParameterPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {if (invocation.getTarget() instanceof ParameterHandler) { System.out.println('ParameterPlugin');}return invocation.proceed(); } @Override public Object plugin(Object target) {if (target instanceof ParameterHandler) { return Plugin.wrap(target, this);}return target; } @Override public void setProperties(Properties properties) {}}@Intercepts({@Signature(type = ResultHandler.class,method = 'handleResult',args = {ResultContext.class})})public class ResultPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {if (invocation.getTarget() instanceof ResultHandler) { System.out.println('ResultPlugin');}return invocation.proceed(); } @Override public Object plugin(Object target) {if (target instanceof ResultHandler) { return Plugin.wrap(target, this);}return target; } @Override public void setProperties(Properties properties) {}}二、攔截器注冊的三種方式

前面介紹了Mybatis的攔截對象及其接口的實現方式,那么在項目中如何注冊攔截器呢?本文中給出三種注冊方式。

1.XML注冊

xml注冊是最基本的方式,是通過在Mybatis配置文件中plugins元素來進行注冊的。一個plugin對應著一個攔截器,在plugin元素可以指定property子元素,在注冊定義攔截器時把對應攔截器的所有property通過Interceptor的setProperties方法注入給攔截器。因此攔截器注冊xml方式如下:

<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE configuration PUBLIC '-//mybatis.org//DTD Config 3.0//EN' 'http://mybatis.org/dtd/mybatis-3-config.dtd'><configuration> <!-- ...... --> <plugins> <plugin interceptor='com.tiantian.mybatis.interceptor.MyInterceptor'> <property name='prop1' value='prop1'/> <property name='prop2' value='prop2'/> </plugin> </plugins> <!-- ...... --></configuration>2.配置類注冊

配置類注冊是指通過Mybatis的配置類中聲明注冊攔截器,配置類注冊也可以通過Properties類給Interceptor的setProperties方法注入參數。具體參考如下:

@Configurationpublic class MyBatisConfig { @Bean public String MyBatisInterceptor(SqlSessionFactory sqlSessionFactory) {UpdatePlugin executorInterceptor = new UpdatePlugin();Properties properties = new Properties();properties.setProperty('prop1', 'value1');// 給攔截器添加自定義參數executorInterceptor.setProperties(properties);sqlSessionFactory.getConfiguration().addInterceptor(executorInterceptor);sqlSessionFactory.getConfiguration().addInterceptor(new StatementPlugin());sqlSessionFactory.getConfiguration().addInterceptor(new ResultPlugin());sqlSessionFactory.getConfiguration().addInterceptor(new ParameterPlugin());// sqlSessionFactory.getConfiguration().addInterceptor(new SelectPlugin());return 'interceptor'; } // 與sqlSessionFactory.getConfiguration().addInterceptor(new SelectPlugin());效果一致 @Bean public SelectPlugin SelectInterceptor() {SelectPlugin interceptor = new SelectPlugin();Properties properties = new Properties();// 調用properties.setProperty方法給攔截器設置自定義參數interceptor.setProperties(properties);return interceptor; }}3.注解方式

通過@Component注解方式是最簡單的方式,在不需要轉遞自定義參數時可以使用,方便快捷。

@Component@Intercepts({@Signature(type = Executor.class,method = 'query',args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class SelectPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {if (invocation.getTarget() instanceof Executor) { System.out.println('SelectPlugin');}return invocation.proceed(); } @Override public Object plugin(Object target) {if (target instanceof Executor) { return Plugin.wrap(target, this);}return target; } @Override public void setProperties(Properties properties) { }}三、ParameterHandler參數改寫-修改時間和修改人統一插入

針對具體的攔截器實現進行描述。日常編碼需求中會碰到修改時需要插入修改的時間和人員,如果要用xml的方式去寫非常麻煩,而通過攔截器的方式可以快速實現全局的插入修改時間和人員。先看代碼:

@Component@Intercepts({@Signature(type = ParameterHandler.class, method = 'setParameters', args = {PreparedStatement.class}),})public class MyBatisInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {// 參數代理if (invocation.getTarget() instanceof ParameterHandler) { System.out.println('ParameterHandler'); // 自動添加操作員信息 autoAddOperatorInfo(invocation);}return invocation.proceed(); } @Override public Object plugin(Object target) {return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } /** * 自動添加操作員信息 * * @param invocation 代理對象 * @throws Throwable 異常 */ private void autoAddOperatorInfo(Invocation invocation) throws Throwable {System.out.println('autoInsertCreatorInfo');// 獲取代理的參數對象ParameterHandlerParameterHandler ph = (ParameterHandler) invocation.getTarget();// 通過MetaObject獲取ParameterHandler的反射內容MetaObject metaObject = MetaObject.forObject(ph,SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,new DefaultReflectorFactory());// 通過MetaObject反射的內容獲取MappedStatementMappedStatement mappedStatement = (MappedStatement) metaObject.getValue('mappedStatement');// 當sql類型為INSERT或UPDATE時,自動插入操作員信息if (mappedStatement.getSqlCommandType() == SqlCommandType.INSERT ||mappedStatement.getSqlCommandType() == SqlCommandType.UPDATE) { // 獲取參數對象 Object obj = ph.getParameterObject(); if (null != obj) {// 通過反射獲取參數對象的屬性Field[] fields = obj.getClass().getDeclaredFields();// 遍歷參數對象的屬性for (Field f : fields) { // 如果sql是INSERT,且存在createdAt屬性 if ('createdAt'.equals(f.getName()) && mappedStatement.getSqlCommandType() == SqlCommandType.INSERT) {// 設置允許訪問反射屬性f.setAccessible(true);// 如果沒有設置createdAt屬性,則自動為createdAt屬性添加當前的時間if (null == f.get(obj)) { // 設置createdAt屬性為當前時間 f.set(obj, LocalDateTime.now());} } // 如果sql是INSERT,且存在createdBy屬性 if ('createdBy'.equals(f.getName()) && mappedStatement.getSqlCommandType() == SqlCommandType.INSERT) {// 設置允許訪問反射屬性f.setAccessible(true);// 如果沒有設置createdBy屬性,則自動為createdBy屬性添加當前登錄的人員if (null == f.get(obj)) { // 設置createdBy屬性為當前登錄的人員 f.set(obj, 0);} } // sql為INSERT或UPDATE時均需要設置updatedAt屬性 if ('updatedAt'.equals(f.getName())) {f.setAccessible(true);if (null == f.get(obj)) { f.set(obj, LocalDateTime.now());} } // sql為INSERT或UPDATE時均需要設置updatedBy屬性 if ('updatedBy'.equals(f.getName())) {f.setAccessible(true);if (null == f.get(obj)) { f.set(obj, 0);} }}// 通過反射獲取ParameterHandler的parameterObject屬性Field parameterObject = ph.getClass().getDeclaredField('parameterObject');// 設置允許訪問parameterObject屬性parameterObject.setAccessible(true);// 將上面設置的新參數對象設置到ParameterHandler的parameterObject屬性parameterObject.set(ph, obj); }} }}

攔截器的接口實現參考前文,這里著重介紹autoAddOperatorInfo方法里的相關類。

1.ParameterHandler

接口源碼:

public interface ParameterHandler { Object getParameterObject(); void setParameters(PreparedStatement var1) throws SQLException; }

提供兩個方法:

getParameterObject是獲取參數對象,可能存在null,需要注意null指針。

setParameters是控制如何設置SQL參數,即sql語句中配置的java對象和jdbc類型對應的關系,例如#{id,jdbcType=INTEGER},id默認類型是javaType=class java.lang.Integer。

該接口有一個默認的實現類,源碼如下:

public class DefaultParameterHandler implements ParameterHandler { private final TypeHandlerRegistry typeHandlerRegistry; private final MappedStatement mappedStatement; private final Object parameterObject; private final BoundSql boundSql; private final Configuration configuration; public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {this.mappedStatement = mappedStatement;this.configuration = mappedStatement.getConfiguration();this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();this.parameterObject = parameterObject;this.boundSql = boundSql; } public Object getParameterObject() {return this.parameterObject; } public void setParameters(PreparedStatement ps) {ErrorContext.instance().activity('setting parameters').object(this.mappedStatement.getParameterMap().getId());List<ParameterMapping> parameterMappings = this.boundSql.getParameterMappings();if (parameterMappings != null) { for(int i = 0; i < parameterMappings.size(); ++i) {ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i);if (parameterMapping.getMode() != ParameterMode.OUT) { String propertyName = parameterMapping.getProperty(); Object value; if (this.boundSql.hasAdditionalParameter(propertyName)) {value = this.boundSql.getAdditionalParameter(propertyName); } else if (this.parameterObject == null) {value = null; } else if (this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) {value = this.parameterObject; } else {MetaObject metaObject = this.configuration.newMetaObject(this.parameterObject);value = metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) {jdbcType = this.configuration.getJdbcTypeForNull(); } try {typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (SQLException | TypeException var10) {throw new TypeException('Could not set parameters for mapping: ' + parameterMapping + '. Cause: ' + var10, var10); }} }} }}

通過DefaultParameterHandler實現類我們知道通過ParameterHandler可以獲取到哪些屬性和方法,其中包括我們下面一個重要的類MappedStatement。

2.MappedStatement

MyBatis的mapper文件中的每個select/update/insert/delete標簽會被解析器解析成一個對應的MappedStatement對象,也就是一個MappedStatement對象描述一條SQL語句。MappedStatement對象屬性如下:

// mapper配置文件名 private String resource; // mybatis的全局信息,如jdbc private Configuration configuration; // 節點的id屬性加命名空間,如:com.example.mybatis.dao.UserMapper.selectByExample private String id; private Integer fetchSize; private Integer timeout; private StatementType statementType; private ResultSetType resultSetType; private SqlSource sqlSource; private Cache cache; private ParameterMap parameterMap; private List<ResultMap> resultMaps; private boolean flushCacheRequired; private boolean useCache; private boolean resultOrdered; // sql語句的類型:select、update、delete、insert private SqlCommandType sqlCommandType; private KeyGenerator keyGenerator; private String[] keyProperties; private String[] keyColumns; private boolean hasNestedResultMaps; private String databaseId; private Log statementLog; private LanguageDriver lang; private String[] resultSets;

在本例中通過MappedStatement對象的sqlCommandType來判斷當前的sql類型是insert、update來進行下一步的操作。

四、通過StatementHandler改寫SQL

StatementHandler是用于封裝JDBC Statement操作,負責對JDBC Statement的操作,如設置參數,并將Statement結果集轉換成List集合。

實現代碼如下:

刪除注解標記

@Target({ElementType.METHOD}) //表示注解的使用范圍@Retention(RetentionPolicy.RUNTIME) //注解的保存時間@Documented //文檔顯示public @interface DeletedAt { boolean has() default true;}

Dao層添加刪除注解,為false時不添加刪除標志

@Mapper public interface AdminProjectDao { @DeletedAt(has = false) List<AdminProjectPo> selectProjects(AdminProjectPo po); }

攔截器通過刪除注解標記判斷是否添加刪除標志

@Component@Intercepts({@Signature(type = StatementHandler.class, method = 'prepare', args = {Connection.class, Integer.class}),})public class MyBatisInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable {if (invocation.getTarget() instanceof StatementHandler) { System.out.println('StatementHandler'); checkHasDeletedAtField(invocation);}return invocation.proceed(); } @Override public Object plugin(Object target) {return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } /** * 檢查查詢是否需要添加刪除標志字段 * * @param invocation 代理對象 * @throws Throwable 異常 */ private void checkHasDeletedAtField(Invocation invocation) throws Throwable {System.out.println('checkHasDeletedAtField');StatementHandler statementHandler = (StatementHandler) invocation.getTarget();// 通過MetaObject訪問對象的屬性MetaObject metaObject = MetaObject.forObject(statementHandler,SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,new DefaultReflectorFactory());// 獲取成員變量mappedStatementMappedStatement mappedStatement = (MappedStatement) metaObject.getValue('delegate.mappedStatement');// 如果sql類型是查詢if (mappedStatement.getSqlCommandType() == SqlCommandType.SELECT) { // 獲取刪除注解標志 DeletedAt annotation = null; String id = mappedStatement.getId(); String className = id.substring(0, id.lastIndexOf('.')); String methodName = id.substring(id.lastIndexOf('.') + 1); Class<?> aClass = Class.forName(className); Method[] declaredMethods = aClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) {declaredMethod.setAccessible(true);//方法名相同,并且注解是DeletedAtif (methodName.equals(declaredMethod.getName()) && declaredMethod.isAnnotationPresent(DeletedAt.class)) { annotation = declaredMethod.getAnnotation(DeletedAt.class);} } // 如果注解不存在或者注解為true(默認為true) 則為mysql語句增加刪除標志 if (annotation == null || annotation.has()) {BoundSql boundSql = statementHandler.getBoundSql();//獲取到原始sql語句String sql = boundSql.getSql();//通過反射修改sql語句Field field = boundSql.getClass().getDeclaredField('sql');field.setAccessible(true);String newSql = sql.replaceAll('9=9', '9=9 and deleted_at is null ');field.set(boundSql, newSql); }} }}

在SQL語句替換上需要能識別到要被替換的內容,因此在xml的sql語句中加入特殊標志'9=9',該標志不影響原來SQL的執行結果,不同的過濾條件可以設置不同的標志,是一個比較巧妙的替換方式。

以上就是MyBatis攔截器的原理與使用的詳細內容,更多關于MyBatis攔截器的資料請關注好吧啦網其它相關文章!

標簽: Mybatis 數據庫
相關文章:
主站蜘蛛池模板: 精品伦一区二区三区免费视频 | 国产猛烈尖叫高潮视频免费 | 少妇扒开腿让我爽了一夜 | 亚洲国产精华液网站w | 黄色激情在线观看 | 偷拍视频一区二区 | 3d动漫啪啪精品一区二区中文字幕 | 国产美女91呻吟求 | 情趣蕾丝内衣少妇啪啪av | 欧美品牌jizzhd欧美 | 49vv看片免费| 久久福利网站 | 不卡无码人妻一区二区三区 | 91丨porny丨在线中文 | 粉豆av| 国产又嫩又黄又猛视频在线观看 | 久久国产精| 亚洲精品18在线观看 | 小草社区视频在线观看 | 日本一本高清 | 国产 欧美 在线 | 久久久久久免费看 | 日韩精品中文字幕无码一区 | 色综合狠狠| 中文字幕在线播放一区 | 国产一线在线观看 | 日本网站在线免费观看 | 亚洲中文字幕无码久久精品1 | 久草中文在线视频 | 国产精品婷婷久久爽一下 | 国产疯狂伦交大片 | 亚洲第一女人av | 午夜影院在线免费观看视频 | 国产精品色婷婷久久99精品 | 99久久精品日本一区二区免费 | 久久精品—区二区三区 | 欧美偷拍一区二区 | 国产免费不卡av | 久久久性色精品国产免费观看 | 国产精品vⅰdeoxxxx国产 | 91大神在线免费观看 | 成人免费ā片在线观看 | 免费观看一区二区三区视频 | 欧美肥老妇视频 | 97超碰人人澡人人爱学生 | 黄色网址在线免费 | 绯色av一区二区 | 亚洲人成电影网站色mp4 | 国产无遮挡吃胸膜奶免费看 | 亚洲一区 国产精品 | 国产婷婷色综合av蜜臀av | 人妻色综合网站 | 日本少妇做爰免费视频软件 | 91久久夜色精品国产网站 | 国产乱码精品一区二区三区爽爽爽 | 无限看片在线版免费视频大全 | 一本色道久久hezyo加勒比 | 欧美乱妇18p | 免费又黄又爽又猛的毛片 | 99久久精品日本一区二区免费 | 青青草视频成人 | 国产福利酱国产一区二区 | 国产视频久久久久 | 少妇性荡欲午夜性开放视频剧场 | 少妇的肉体k8经典 | 日韩亚洲视频 | 日韩精品一区二区在线观看 | 9色av | 成人无码视频免费播放 | 免费不卡av | 无码av波多野结衣久久 | 182tv成人福利视频免费看 | 99精品欧美一区二区 | 免费999精品国产自在现线 | 92国产精品午夜福利免费 | 黄频在线 | 麻豆一区二区三区蜜桃免费 | 青娱乐精品视频 | 在线a久青草视频在线观看 无套内射极品少妇chinese | 亚洲国产福利一区二区三区 | 56av国产精品久久久久久久 | 91福利社区在线观看 | 美女嘘嘘嘘aaaaaaaa级 | 嫩草嫩草嫩草嫩草嫩草嫩草 | 亚洲精品美女在线观看播放 | 乱熟女高潮一区二区在线 | 国产69精品久久久久久久 | 日本乱偷人妻中文字幕 | 日本一二三不卡 | 毛片视频软件 | 女职员的丝袜 中文字幕 | 亚洲国产真实交换 | 狠狠色婷婷久久综合频道毛片 | 国产二级av | 国产口爆吞精在线视频 | 欧美性色a | 亚洲天天操 | 久久精品成人一区二区三区蜜臀 | 日韩一区二区三区在线免费观看 | 一区二区三区免费观看视频 | 男女深夜福利 | 99久久精品免费看国产免费粉嫩 | 精品二区视频 | 国产精欧美一区二区三区 | 农村脱精光一级 | 女人色偷偷aa久久天堂 | 国产性色av免费观看 | 国产精品白丝喷水在线观看 | 欧美gv在线观看 | 91精品国产高清91久久久久久 | 国产免费视频传媒 | 国产三香港三韩国三级古装 | 丰满少妇高潮惨叫久久久一 | 专干老肥女人88av | 日本黄色特级片 | 亚洲精品电影院 | 国产国产小嫩模无套内谢 | 国产九九热视频 | 国产精品性视频一区二区 | 国产成人免费视频 | 国产区一区二区三区 | 国产综合亚洲精品一区二 | 亚州av一区| 国产乱国产乱 | 免费网站看v片在线观看 | 免费黄色资源 | 成人无高清96免费 | 久久精品亚洲国产奇米99 | 久一视频在线观看 | 少妇裸交aa大片 | 天天热天天干 | 爱爱视频欧美 | 午夜欧美视频 | 欧美激情久久久久 | 国产免费91 | 在线免费观看国产视频 | 日韩在线一区二区 | 日本一级大黄毛片基地 | 亚洲综合色丁香婷婷六月图片 | 久久精品97 | 护士奶头又白又大又好摸视频 | 久久综合日本 | 亚洲成a人 | 99久久中文字幕三级久久日本 | 高清国产精品人妻一区二区 | 欧美成人午夜精品久久久 | 天天躁日日躁很很很躁 | 91资源站| 亚洲精品乱码久久久久久久久久久久 | 成 人 黄 色 网 页 | 国产精品高潮久久 | 欧美色aⅴ欧美综合色 | 无码人妻丰满熟妇区96 | 日韩字幕 | 日本在线视频二区 | 国产综合精品一区二区三区 | 国产又粗又猛又爽视频 | 亚洲成人不卡 | 一区二区国产盗摄色噜噜 | 国产揄拍国内精品对白 | 一级全黄色毛片 | 成人看片黄a免费看视频 | 熟女毛多熟妇人妻在线视频 | 后进极品美女圆润翘臀 | 国产精品久久久久久一区二区三区 | 国产小视频在线观看免费 | 日本xxxxx69hd日本 | 国产日产欧产精品精品首页 | 性初体验美国理论片 | 咪咪色影院 | 欧美jizzhd精品欧美丰满 | 四虎av网站| 欧美性大战久久久久xxx | 精品蜜臀久久久久99网站 | 羞羞动漫在线看免费 | 在线免费一级片 | 色伊人网| 少妇大叫太大太粗太爽了 | av在线播放中文字幕 | 日本无翼乌邪恶大全彩h | 国产码在线播放 | 亚洲乱码国产乱码精品精的特点 | 无码人妻丰满熟妇区毛片18 | 丝袜 中出 制服 人妻 美腿 | 91国产丝袜脚调教 | 欧美日韩一区二区三区在线观看视频 | 国产人成在线视频 | 尤物久久| 91成人短视频在线观看 | 天天躁日日躁狠狠躁视频2021 | 午夜蜜汁一区二区三区av | 美女性感毛片 | 4438x成人网一全国最大色成网站 | 久久99热狠狠色精品一区 | 日韩欧美在线视频观看 | 午夜乱码爽中文一区二区 | 中文字幕 自拍偷拍 | 国产精品亲子乱子伦xxxx裸 | sese在线| 亚洲精品无码永久在线观看性色 | 久久久无码精品午夜 | 国产一区二区三区视频 | 五月激情小说 | a∨变态另类天堂无码专区 人妻丰满熟妇av无码区不卡 | av在线一| 国毛片| 久久成人在线 | 人人超碰在线 | va在线观看 | 偷拍夫妻性生活 | 久久99青青精品免费观看 | 精品国产久 | 成人av高清在线观看 | 欧美成人精品三级在线观看播放 | 正在播放超嫩在线播放 | 欧美国产一区二区三区 | 午夜天堂精品久久久久 | 日本成人在线免费观看 | h小视频在线观看 | 被灌满精子的少妇视频 | 国产美女极度色诱视频www | 精品66| 后进极品美女圆润翘臀 | 国内精品久久久久久久久久清纯 | 久久久久久久久久一区二区三区 | 国产精品国产三级国产aⅴ9色 | 国产成人精品一区二区在线小狼 | 久久综合狠狠综合五十路 | 女高中生第一次破苞av | 亚洲日韩av无码一区二区三区 | 亚洲精品一区二区在线观看 | 成人深夜福利 | 人人妻久久人人澡人人爽人人精品 | 风韵丰满熟妇啪啪区老老熟妇 | 国产免费又爽又刺激在线观看 | 色久综合网 | 国产亚洲精品久久yy50 | 欧美sese| 亚洲综合精品一区二区三区 | www.黄色网 | 久久欧美精品久久天美腿丝袜 | 少妇高清精品毛片在线视频 | 国产无限制自拍 | 国产69精品麻豆 | 日韩性生交大片免费看 | 久久黄色成人 | 91亚洲国产精品 | 91日日日 | 日本成人在线免费视频 | 丰满少妇高潮惨叫久久久一 | av观看网 | 亚洲欧洲无码一区二区三区 | 日本乱子伦xxxx | 四虎8848精品成人免费网站 | √天堂资源网最新版在线 | 粉嫩欧美一区二区三区高清影视 | 国产99re| 国产a网| 色婷婷久久久亚洲一区二区三区 | 无遮挡1000部拍拍拍免费 | 视频一区中文字幕 | 久久精品爱| 亚洲 精品 主播 自拍 | 456成人网| 人人爽久久涩噜噜噜小说 | 欧美另类一区 | 亚洲成人精品在线观看 | 日韩av综合在线 | 亚洲一区二区三区视频在线 | 国产在线观看你懂得 | 色黄啪啪网 | 亚洲色大成网站www久久九九 | 7777精品久久久久久 | 中文字幕免费高清在线观看 | 亚洲成a v人片在线观看 | 成人日批 | 一区二区三区回区在观看免费视频 | 超碰2025| 国产成人精选视频在线观看 | 精品国产乱码久久久久久婷婷 | 91九色在线播放 | 少妇一区二区三区四区 | 成人孕妇专区做爰高潮 | 久久国产精品广西柳州门 | 国产精品成久久久久三级6二k | 午夜一级大片 | 在线资源av| 曰韩一级片 | 日韩精品久久久久久免费 | 亚洲国产美女久久久久 | 亚洲www啪成人一区二区 | 久久成人18免费网站 | 激情xxxx | 欧美久久久久久久久久久久久久 | 偷拍青青草| 在办公室被c到呻吟的动态图 | 国产另类重口一 | 国产黄色片免费看 | av片在线观看| 久久精品日韩 | 欧美美女性生活 | 亚洲v在线观看 | 欧美在线影院 | 国产精品入口传媒小说 | 久久九九免费 | 国产精品午夜在线观看 | 三级理论中文字幕在线播放 | 国产乱人伦 | 日本在线资源 | 美国黄色毛片 | 久久精品香蕉 | 亚洲 高清 成人 动漫 | 欧洲熟妇色xxxx欧美老妇多毛网站 | 国产精品久久久久一区二区三区 | 午夜网站在线观看 | 国产专业剧情av在线 | 亚洲激情五月婷婷 | 国产精品性 | 亚洲欧美激情精品一区二区 | 欧美在线播放一区 | 亚洲免费视频一区 | 国产a级精品毛片 | 最新av在线网站 | 97久久久久| 色yeye香蕉凹凸视频在线观看 | 91精品国产高清一区二区三密臀 | 国产激情久久久久久 | 法国啄木系列成人av | 久久久久久久久久91 | 欧美在线影院 | 久久99精品国产麻豆婷婷洗澡 | 高清成人 | 欧美猛交ⅹxxx乱大交视频 | 欧美另类极品 | 亚洲自偷自偷偷色无码中文 | aaaaa少妇高潮大片 | 91精品国产色综合久久久浪潮 | 免费无遮挡在线观看视频网站 | 欧美性猛交xxx乱大交3蜜桃 | 美女视频黄8频a美女大全 | 精品超清无码视频在线观看 | 久久精品97 | 综合天堂av久久久久久久 | 国产精品美女久久久久久久久 | 亚洲自拍偷拍精品 | 欧美片一区二区 | 国产综合第一页 | av片在线观看免费 | 日韩1区3区4区第一页 | 91国内精品自线在拍白富美 | 欧美日韩精品久久久 | 中文字幕免费高清网站 | 手机在线观看毛片 | 国产福利一区二区三区视频 | 国产日韩欧美一区二区三区乱码 | 亚洲青春草 | 在线观看欧美日韩视频 | 亚洲国产精品第一区二区 | 青青视频在线免费观看 | 麻豆一区二区99久久久久 | 九九香蕉视频 | 亚洲欧美一区二区三区 | 天天插天天操 | 成人av免费 | www.欧美激情 | 在线色导航 | 亚洲乱亚洲乱少妇无码99p | 91网站在线看 | 成人综合激情网 | 久久亚洲私人国产精品 | 最近免费中文字幕mv在线视频3 | 久久国产一区二区三区 | 欧美国产一级片 | 国产日韩欧美不卡 | 动漫美女无遮挡免费 | 妺妺窝人体色www看美女 | 欧美黑人狂野猛交老妇 | 亚洲精品午夜一区人人爽 | 国产亚洲精品美女久久久 | 中国熟妇牲交视频 | 国产一级片免费播放 | 椎名由奈在线观看 | 亚洲国产精品肉丝袜久久 | 国产男女猛烈无遮挡免费视频网站 | 亚洲淫欲| 好吊妞人成视频在线观看27du | 亚洲丝袜色图 | 欧美在线观看一区二区 | 免费在线视频一区 | 久久国产精品99久久人人澡 | 青青操网| 国产又黄又粗的视频 | 91精品国产色综合久久不卡粉嫩 | 丝袜足脚交91精品 | 免费在线观看网址入口 | 天天摸天天摸 | 久久伊人av | 亚洲精品在线观看免费 | 亚洲精品成人区在线观看 | 少妇情理伦片丰满午夜在线观看 | 国产白丝精品91爽爽久久 | 亚洲成人h | 亚洲一级av毛片 | 久久天堂av综合合色蜜桃网 | 国产精品视频在 | 97人人草| 亚洲熟妇av一区二区三区漫画 | 色网站在线免费观看 | 华人少妇被黑人粗大的猛烈进 | 亚洲最新网址 | 屁屁国产第一页草草影院 | 在线日韩成人 | 999国产视频| 亚洲男人天堂久久 | 国产亚洲精品久久19p | 青青草一区二区 | 免费观看成人欧美www色 | 国产精品嫩草影视久久久 | 91美女片黄在线观看成欢阁 | 一区二区av | 天天做天天爱天天综合网2021 | 久久久久女人精品毛片九一 | 欧美激情导航 | 欧美又粗又深又猛又爽啪啪九色 | 亚洲视频在线免费播放 | 亚洲国产成人久久 | 91精品国产乱码久久久久 | 国产视频精品在线 | 国产美女免费网站 | 精品国产一区二区三区免费 | 欧美喷潮久久久xxxxx | 久久久久亚洲ai毛片换脸星大全 | 日日干天天爽 | 另类av小说 | 日韩一区二区三区在线免费观看 | 91国内精品久久 | 天天噜夜夜噜 | 99精品欧美一区二区三区综合在线 | 亚洲性激情 | 色视频在线观看网站 | 8x拔播拔播x8国产精品 | 精品少妇久久久久久888优播 | 五十岁熟韵母乱视国产 | 色窝av| 欧美色图一区二区 | 男人的天堂网av | 91性高潮久久久久久久 | 亚洲乱妇老熟女爽到高潮的片 | 欧美亚洲亚洲日韩在线影院 | 亚洲天堂高清 | 天天干夜夜嗨 | 成年人免费看视频 | 亚洲欧美国产另类 | 精品人伦一区二区三区蜜桃免费 | 狠狠躁夜夜躁人蜜臀av小说 | 操操综合网 | 国产一极片 | 色盈盈影院 | 天天综合日韩 | 国产小视频在线观看 | 国产三级高清一区二区 | 成人亚洲欧美成αⅴ人在线观看 | 日本强好片久久久久久aaa | 成人做爰高潮片免费视频美国 | 97人人在线视频 | 国产三级三级看三级 | 91麻豆精品国产91久久久点播时间 | 日韩精品在线观 | 六月丁香av | 国产中文区3幕区2021 | jazzjazz国产精品麻豆 | 国产人成看黄久久久久久久久 | 牲高潮99爽久久久久777 | 成人精品一区日本无码网 | 91xxx在线观看| 亚洲色图日韩 | 男男毛片 | 亚洲欧美另类激情综合区 | 欧美精品在线免费观看 | 日日碰狠狠躁久久躁96avv | 人妻被按摩到潮喷中文字幕 | 天天爽影院一区二区在线影院 | 毛片网站大全 | 国产午夜精品av一区二区麻豆 | www五月| 国产丝袜在线 | 成人看片黄a免费看视频 | 成人羞羞国产免费软件动漫 | www黄色在线观看 | 裸体女人a级一片 | 在线播放日韩 | 国产一在线精品一区在线观看 | 国产精品毛片一区二区三区 | 步兵在线一区二区三区 | 人妻夜夜爽天天爽三区丁香花 | 日韩欧美在线看 | 欧美剧场 | 中文字幕久久999及 中文字幕久久av | 亚洲奶汁xxxx哺乳期 | 亚洲 卡通 欧美 制服 中文 | 国产又色又爽无遮挡免费 | 免费激情网址 | 久久九九网站 | 7788色淫视频观看日本人 | 国产精品女人久久久 | 久久久老熟女一区二区三区 | 嫩草影院在线观看91麻豆 | 亚洲精品视频一区二区三区 | 91看片在线 | 一级特黄毛片 | 亚洲精品成人网站在线观看 | 国产交换配乱淫视频免费 | 国产精品第一国产精品 | 亚洲成av人片在线观看 | 亚洲人精品亚洲人成在线 | 超碰美女在线 | 日本xxxwww | 中国丰满少妇熟乱xxxx | 成人在线免费播放视频 | 丁香激情综合久久伊人久久 | 在线观看视频中文字幕 | 黄色av免费网站 | 欧美自拍偷拍一区二区 | 女人14毛片毛片毛片毛片区二 | 2018国产在线| 五月婷婷激情在线 | 精品福利视频一区二区 | 潘金莲激情呻吟欲求不满视频 | 操操操日日日 | 国产男女猛烈无遮掩视频免费网站 | 白丝久久| 在线视频观看一区二区 | 日本免费在线观看视频 | 欧美日韩视频无码一区二区三 | аⅴ资源新版在线天堂 | 日本人妻丰满熟妇久久久久久 | 特级西西444www大精品视频免费看 | 亚洲欧洲免费无码 | 性——交——性——乱免费的 | 亚洲精品另类 | 羞羞动漫在线看免费 | 欧美老熟妇喷水 | 一级aa毛片 | 加勒比久久综合网天天 | 亚洲乱码国产乱码精品精软件 | 日韩视频无码中字免费观 | 91视频青青草 | 欧美一区二区三区四区五区 | 日韩一区二区三 | 喷潮在线| 国产一级免费 | 特级西西444www大精品视频 | 日韩欧美一中文字暮视频 | 国产精品一区二区欧美 | 色妞综合网 | 一本色道久久88—综合亚洲精品 | 永久免费看片在线播放 | 午夜av中文字幕 | 国a产久v久伊人 | 国产自在自线午夜精品 | mm1313亚洲国产精品无码试看 | 91精产国品一二三区在线观看 | 亚洲一区二区影院 | 国产无遮挡又黄又爽在线视频 | 中文字幕网伦射乱中文 | 日本三级吃奶乳视频在线播放 | 人人看超碰 | 亚洲人成人无码www 国产亚洲精品久久久久秋霞 | 91gao| 国产麻豆剧果冻传媒星空视频 | 激情一区 | 好男人社区www在线观看 | 国产sm鞭打调教女m视频 | 影音先锋人妻啪啪av资源网站 | 日韩欧美一级大片 | 秋霞一级全黄大片 | 国产精品99在线观看 | 国产欧美视频在线播放 | 日躁夜躁狠狠躁2001 | 国产高清在线观看 | 韩国少妇xxxx搡xxxx搡 | 日韩欧美精品在线 | 欧美日本国产在线 | 色人阁婷婷 | 色狠狠色狠狠综合天天 | 在线亚洲观看 | 欧美美女性生活视频 | 久久免费大片 | 大陆明星乱淫(高h)小说 | 免费观看又污又黄的网站 | 日本熟妇丰满大白屁毛片 | 深夜成人福利视频 | 欧美日韩五月天 | 亚洲成a人片77777kkkk1在线观看 | 日日碰狠狠添天天爽 | 午夜影视免费 | 成熟丰满熟妇av无码区 | 日本大尺度床戏揉捏胸 | 性做久久久久久久 | 一区视频在线播放 | 久久久久久成人毛片免费看 | 亚洲国产精品成人综合色在线婷婷 | 国产乱国产乱 | 少妇精品视频一区二区免费看 | 欧美高清性色生活片免费观看 | 九九九九九九九九九 | 国产成人精品日本亚洲专区61 | 欧美另类极品videosbest最新版本 | 大尺度激情吻胸视频 | a天堂v| 1000部拍拍拍18勿入免费视频下载 | 亚洲熟妇久久国产精品 | 国产欧美日韩久久久久 | 欧美一区二区视频在线 | 成人av免费 |