クエリページ全体の実行コードを共有する前に、最初に実行プロセスを理解します。
1.一般的に、MyBatisプラグインインターセプターを使用してSQL実行前にインターセプトし、クエリステートメントにXXを制限する
2。ページオブジェクトを使用して、実行プロセス全体を実行します。このページオブジェクトでは、Javaにフロントエンドページネーションコンポーネントを作成する必要があります。
3.このページネーションアーキテクチャをサポートするために、3層エンティティ、DAO、およびサービスの比較的完全なセットを使用してください
4.このページで使用されるいくつかの補助クラス
注:多くのコンテンツが共有されています。必要な瓶は1つずつリストしません。このページネーション関数を使用するときは、夜にJARパッケージを探してください。 Mavenはバージョンの競合やその他の利点を減らすことができるため、Mavenパッケージを使用して可能な限りインポートします。
この簡単なページング機能をできるだけ早く使用できるとしか言えません。理解していない場合は、QQに追加して一緒に話し合ってください。誓わないでください!また、この記事は比較的大きいかもしれませんが、しばらく時間がかかり、それを読んで練習することは間違いなく多くのことを得るでしょう。
ステップ1:このトピックは、ページングの方法を中心に展開しているため、MyBatisから始めましょう。まず、MyBatisに関連する2つの重要な構成ファイルを簡単に理解するために取り出します。 1つはmybatis-config.xmlで、もう1つはエンティティに対応するマッパー構成ファイルです。構成ファイルにコメントを書きます。誰もが一目でそれを理解します。
mybatis-config.xml
<!doctype configuration public " - // mybatis.org//dtd config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <! - グローバルパラメーター - > <設定> <! - > <name = "cacheenabled" value = "false"/> <! - 怠zyなロードをグローバルに有効または無効にします。無効にすると、関連するすべてのオブジェクトが即座にロードされます。 - > <name = "lazyloadingEnabled" value = "true"/> <! - 有効にすると、怠zyなロードプロパティを持つオブジェクトは、呼び出されたときに任意のプロパティを完全にロードします。それ以外の場合、各プロパティは必要に応じてロードされます。 - > <name = "aggressivelazyloading" value = "true"/> <! - 単一のSQLが複数のデータセットを返すことを許可するかどうか(ドライバーの互換性に応じて)デフォルト:true-> <name = "multipleresultsetsenabled" value = "true"/> < name = "usecolumnlabel" value = "true"/> <! - jdbcがプライマリキーを生成することを許可します。ドライブサポートが必要です。 Trueに設定されている場合、この設定は生成されたプライマリキーを強制します。一部のドライブは互換性がありませんが、実行できます。デフォルト:false - > <name = "usegeneratedkeys" value = "false"/> <! - mybatisがデータベーステーブルの列を自動的にマッピングする方法なしに指定します。ステートメントとバッチの更新) - > <name = "defaultexecutortype" value = "simple"/> <! - キャメル命名法を使用してフィールドを変換します。 - > <name = "Mapunderscoretocamelcase" value = "true"/> <! - ローカルキャッシュ範囲セッションの設定:データ共有ステートメントがあります。ステートメントスコープ(これはデータ共有ではありません)defalut:> <name = "localcachescope" value = "session"/> <! null値を挿入する場合 - > <name = "jdbctypefornull" value = "null"/> <setting name = "logprefix" value = "dao。"/> </settings> <! - エイリアスは短いJavaタイプの名前です - > <typealas> <typealias> <typealias type = " Alias = "user"> </typealias> <typealias type = "com.store.base.secondmodel.pratice.model.product" alias = "product"> </typealias> <typealias type = "com.store.base.secondmodel.base.base.base.構成、ここにmybatis用に構成されたページインターセプターがあります。このページインターセプターを実装する必要があります - > <プラグインインターセプター= "com.store.base.secondmodel.base.pageInterceptor.PaginationInterceptor"/> </blugins> </configuration>
ProductMapper.xmlはテストオブジェクトとして使用されます。このマッパーファイルは、使用する必要があるクエリステートメントを構成するだけです。
<?xml version = "1.0" encoding = "utf-8"?> <!doctype mapper public " - // mybatis.org//dtd mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" namespace = "com.store.base.secondmodel.pratice.dao.productdao"> <sql id = "basecolumns"> id、product_name as productname、froduct_no as productno、as price </sql> <select id = "findlist" resultType = "com.store.base.secondmodel.pratice.model.product"> select <include refid = "basecolumns"/> from t_store_product </select> </mapper>
ステップ2:次に、このページネーションインターセプターの詳細な分析と学習を実施し、主に次のクラスとそれらの対応するインターフェイスを含めます
(1)ベースインターセプターインターセプターベーシッククラス
(2)PaginationInterceptor Paginationプラグインクラスを使用し、上記の基本クラスを継承します
(3)SQLHELPERは、主に事前にカウントステートメントを実行し、完全なページネーションステートメント全体を取得するために使用されます。
(4)方言、mysqldialectは、主にデータベースが制限ステートメントをサポートしているかどうかに使用され、完全な制限ステートメントをカプセル化するかどうかに使用されます
以下は、これらのカテゴリの共有表示です
baseinterceptor.java
パッケージcom.store.base.secondmodel.base.pageInterceptor; java.io.serializableをインポートします。 java.util.propertiesをインポートします。 org.apache.ibatis.logging.logをインポートします。 org.apache.ibatis.logging.logfactoryをインポートします。 org.apache.ibatis.plugin.interceptorをインポートします。 com.store.base.secondmodel.base.globalをインポートします。 com.store.base.secondmodel.base.pageをインポートします。 com.store.base.secondmodel.base.dialect.dialectをインポートします。 com.store.base.secondmodel.base.dialect.mysqldialectをインポートします。 com.store.base.util.Reflectionsをインポートします。 / ** * MyBatis Pagination Interceptor Base Class * @author yiyong_wu * */ public Abstract class Baseintector Implations Interceptor、serializable {private static final long serialversionuid = 1l;保護された静的最終文字列ページ= "page";保護された静的最終文字列Delegate = "Delegate";保護されたstatic final string mapped_statement = "mappedstatement";保護されたlog log = logfactory.getLog(this.getClass());保護された方言方言; / ***パラメーターを変換して確認* @param parameterobject parameterobject parameterobject* @param page pagination object* @return pagination object* @throws nosuchfieldexceptionパラメーターは見つかりません*/ @suppresswarnings( "unchecked")保護されたstaticページ<オブジェクト<オブジェクト< instanceof page){return(page <object>)parameterobject; } else {return(page <object>)reflections.getFieldValue(parameterObject、page); }} catch(例外e){return null; }} /***プロパティを設定し、カスタム方言クラスをサポートし、データベースを策定する方法* <code> dialectclass < /code>、カスタム方言クラス。これは、 * <ode> dbms </ode>データベースタイプを構成せずに構成できます。プラグインでサポートされているデータベース * <code> sqlpattern </code> sql id * @param pプロパティ */保護されたvoid initproperties(Properties p){allect firect = null; string dbtype = global.getConfig( "jdbc.type"); if( "mysql" .equals(dbtype)){dierect = new mysqldialect(); } if(dalect == null){throw new runtimeexception( "mybatis方言エラー。"); }方言=方言; }}PaginationInterceptor.java
パッケージcom.store.base.secondmodel.base.pageInterceptor; java.util.propertiesをインポートします。 org.apache.ibatis.executor.executorをインポートします。 Import org.apache.ibatis.mapping.boundsql; Import org.apache.ibatis.mapping.mappedStatement; Import org.apache.ibatis.mapping.sqlsource; org.apache.ibatis.plugin.interceptsをインポートします。 Import org.apache.ibatis.plugin.invocation; org.apache.ibatis.pluginをインポートします。 org.apache.ibatis.plugin.signatureをインポートします。 org.apache.ibatis.reflection.metaobjectをインポートします。 Import org.apache.ibatis.session.resulthandler; Import org.apache.ibatis.session.rowbounds; com.store.base.secondmodel.base.pageをインポートします。 com.store.base.secondmodel.base.util.stringutilsをインポートします。 com.store.base.util.Reflectionsをインポートします。 /***データベースのページングプラグインは、クエリステートメントのみを傍受します。 * @author yiyong_wu * */ @intercepts({@signature(type = executor.class、method = "query"、args = {mappedstatement.class、object.class、rowbounds.class、resulthandler.class})})paginterceptor extender extensictor {lime sitatic @Override public Object Intercept(Invocation Invocation)Throws Throwable {final MappedStatement MappedStatement =(mappedStatement)rivocation.getargs()[0]; Object Parameter = Invocation.GetArgs()[1]; BoundsQl BoundSql = MappedStatement.GetBoundSQL(パラメーター); object parameterObject = bundsql.getParameterObject(); //ページネーションパラメーターオブジェクトページを取得<オブジェクト>ページ= null; if(parameterObject!= null){page = convertParameter(parameterobject、page); } //ページングオブジェクトが設定されている場合、ページは実行されます(page!= null && page.getPagesize()!= -1){if(stringutils.isblank(boundsql.getsql()))){return null; } string originalsql = boundsql.getsql()。trim(); //レコードの総数を取得page.setCount(sqlhelper.getCount(originalalsql、null、mappedstatement、parameterobject、bundsql、log)); // Pagination Queryローカライズされたオブジェクトは、データベースを変更し、実装文字列Pagesql = sqlhelper.generatepagesql(originalsql、page、dierect)の変更に注意してください。 Invocation.getArgs()[2] = new RowBounds(rowBounds.no_row_offset、rowbounds.no_row_limit); BoundsQl NewBoundSQL = new BoundSQL(MappedStatement.GetConfiguration()、PagesQl、Boundsql.getParametermAppings()、Boundsql.getParameterObject()); // mybatis pagination foreachパラメーターの故障開始if(reflections.getFieldValue(boundsql、 "metaparameters") Reflections.SetFieldValue(NewBoundSQL、 "Metaparameters"、Mo); } // mybatis pagination foreachパラメーター障害end mappedstatement newms = copyfrommapptatement(mappedStatement、new Boundsqlsqlsource(newboundSQL)); Invocation.getArgs()[0] = newms; } returnInvocation.proceed(); } @Override public Object Plugin(Object Target){return plugin.wrap(target、this); } @Override public void setProperties(プロパティプロパティ){super.initproperties(Properties); } private mappedStatement copyfrommapptatement(MappedStatement MS、sqlSource newsqlSource){mappedStatement.builder builder = new MappedStatement.Builder(ms.getConfiguration()、ms.getid()、newsqlsource、ms.getsqlcommandtype(); builder.resource(ms.getResource()); builder.fetchsize(ms.getfetchsize()); builder.statementType(ms.getStatementType()); Builder.KeyGenerator(Ms.GetKeyGenerator()); if(ms.getKeyProperties()!= null){for(string keyproperty:ms.getKeyProperties()){builder.keyProperty(keyproperty); }} builder.timeout(ms.gettimeout()); builder.parametermap(ms.getparametermap()); Builder.ResultMaps(ms.getResultMaps()); builder.cache(ms.getcache()); return builder.build(); } public static class bundsqlsqlsourceはsqlsource {boundsql bundsql; public Bundsqlsqlsource(Bundsql Bundsql){this.boundsql = Bundsql; } @Override public Bundsql getBoundSql(object parameterobject){return boundsql; }}}sqlhelper.java
パッケージcom.store.base.secondmodel.base.pageInterceptor; Java.sql.Connectionをインポートします。 Java.sql.preparedStatementをインポートします。 java.sql.resultsetをインポートします。 java.sql.sqlexceptionをインポートします。 java.util.listをインポートします。 java.util.regex.matcherをインポートします。 java.util.regex.patternをインポートします。 org.apache.ibatis.executor.errorcontextをインポートします。 org.apache.ibatis.executor.executorexceptionをインポートします。 org.apache.ibatis.logging.logをインポートします。 Import org.apache.ibatis.mapping.boundsql; Import org.apache.ibatis.mapping.mappedStatement; org.apache.ibatis.mapping.parametermappingをインポートします。 org.apache.ibatis.mapping.parametermodeをインポートします。 org.apache.ibatis.reflection.metaobjectをインポートします。 org.apache.ibatis.reflection.property.propertytokenizerをインポートします。 org.apache.ibatis.scripting.xmltags.foreachsqlnodeをインポートします。 Import org.apache.ibatis.session.configuration; org.apache.ibatis.type.typehandlerをインポートします。 Import org.apache.ibatis.type.typehandlerregistry; com.store.base.secondmodel.base.globalをインポートします。 com.store.base.secondmodel.base.pageをインポートします。 com.store.base.secondmodel.base.dialect.dialectをインポートします。 com.store.base.secondmodel.base.util.stringutilsをインポートします。 com.store.base.util.Reflectionsをインポートします。 /*** SQLツールクラス* @author yiyong_wu** /public class sqlhelper { /***デフォルトのプライベートコンストラクター* /private sqlhelper(){} /*** sqlパラメーターの値を設定します(?)、org.apache.ibatis.executor.execturation.defaultparmetarmeter.defaultparmetarmeter声明の目的。 * @param mappedstatement mappedstatement * @param boundsql sql * @param parameterobject parameterobject parameterobject @throws java.sql.sqlexceptionデータベース例外 */ @suppresswarnings( "unchecked")settatementementement ps、mappedstate boundsql、object parameterObject)splecsection {errorcontext.instance()。アクティビティ( "パラメーターの設定")。リスト<パラメーターマッピング> parametermappings = bundsql.getParametermappings(); if(parametermappings!= null){configuration configuration = mappedstatement.getConfiguration(); TypeHandlerRegistry TypeHandlerRegistry = configuration.getTypeHandlerRegistry(); MetaObject MetaObject = parameterObject == null? null:configuration.newmetaobject(parameterobject); for(int i = 0; i <parametermappings.size(); i ++){parametermapping parametermapping = parametermappings.get(i); if(parametermapping.getMode()!= parametermode.out){object値; string propertyname = parametermapping.getProperty(); PropertyTokenizer Prop = new PropertyTokenizer(propertyName); if(parameterObject == null){value = null; } else if(typehandlerregistry.hastypehandler(parameterobject.getClass())){value = parameterObject; } else if(boundsql.hasadditionalparameter(propertyname)){value = boundsql.getadditionalParameter(propertyName); } else if(propertyname.startswith(foreachsqlnode.item_prefix)&& bundsql.hasadditionalParameter(prop.getName())){value = boundsql.getAdtionalParameter(prop.getName()); if(value!= null){value = configuration.newmetaobject(value).getValue(propertyname.substring(prop.getName()。length())); }} else {value = metaobject == null? null:metaobject.getValue(propertyName); } @suppresswarnings( "rawTypes")typehandler typehandler = parametermapping.getTypeHandler(); if(typehandler == null){show new executorexception( "statement" + mappedstatement.getid())のパラメーター " + propertyname +"には型型ハンドラーが見つかりませんでした。 } typehandler.setParameter(ps、i + 1、value、parametermapping.getjdbctype()); }}}} / ***クエリ合計レコード* @Param SQL SQL Statement* @Param Connection Database Connection* @Param MappedStatement Mapped* @Param ParameterObject Parameter* @Param BoundsQl* @return合計記録MappedStatement MappedStatement、Final Object ParameterObject、final Boundsql BoundsQl、log log)Strows sqlexception {string dbname = global.getconfig( "jdbc.type");最終文字列countSQL; if( "oracle" .equals(dbname)){countsql = "select count(1)from(" + sql + ")tmp_count"; } else {countSql = "from(" + remoforders(sql) + ")tmp_count"; }接続conn = connection; represedStatement PS = null;結果rs = null; try {if(log.isdebugenabled()){log.debug( "count sql:" + stringutils.replaceeach(countsql、new string [] {"/n"、 "/t"}、new String [] {"" "、" "}); } if(conn == null){conn = mappedstatement.getConfiguration()。getEnvironment()。getDataSource()。getConnection(); } ps = conn.preparestatement(countsql); bundsql countbs = new Boundsql(mappedStatement.getConfiguration()、CountSql、Bundsql.getParametermAppings()、parameterObject); // mybatis pagination foreachパラメーターの故障開始if(reflections.getFieldValue(boundsql、 "metaparameters") Reflections.SetFieldValue(Countbs、 "Metaparameters"、Mo); } // mybatis pagination foreachパラメーター障害ed sqlhelper.setParameters(PS、MappedStatement、CountBS、ParameterObject); rs = ps.executequery(); int count = 0; if(rs.next()){count = rs.getint(1); } return count; }最後に{if(rs!= null){rs.Close(); } if(ps!= null){ps.close(); } if(conn!= null){conn.close(); }}} / ***データベースの方言に従って特定のページを生成* @Param SQL Mapper* @Param SQL STATEMATE* @PARAMページページングオブジェクト* @Param方言の方言タイプ* @returnページングSQL* / public Static String GeneratePagesQL(String SQL、Page <Object> page) dierect.getlimitstring(sql、page.getFirstreSult()、page.getMaxResults()); } else {return sql; }} /*** qlstringの選択句を削除します。 * @param hql * @return */ @suppresswarnings( "unused")private static string removeSelect(string qlstring){int beginpos = qlstring.tolowercase()。indexof( "from"); qlstring.substring(beginpos)を返します。 } /*** HQLのOrderby句を削除します。 *@param hql *@return */private static string remodororders(string qlstring){pattern p = pattern.compile( "order // s *by [// w | // s | // s] *"、pattern.case_insensitive); Matcher M = P.Matcher(QLString); stringbuffer sb = new StringBuffer(); while(m.find()){m.appendReplacement(sb、 ""); } m.appendtail(sb); return sb.tostring(); }}Dialect.javaインターフェイス
パッケージcom.store.base.secondmodel.base.dialect; / *** hibernateと同様ですが、ページング部分のみが簡素化されます* @author yiyong_wu**/ public interface方言{/ ***データベース自体はページングのための現在のページングクエリメソッドをサポートしています*データベースがサポートしない場合、データベースページングはページングされません** @return: / ** * SQLをページネーションSQLに変換し、ページングSQLを個別に呼び出します * * @Param SQL SQLステートメント * @Param Offset starts * @param limeページごとに表示されるレコードの数 * @return sql for paginate query */ public string getlimitstring(int offset、intset、intset); }mysqldialect.java
パッケージcom.store.base.secondmodel.base.dialect; / ** * mysql方言の実装 * @author yiyong_wu * */ public class mysqldialect実装{@override public boolean supportlimit(){return true; } @Override public String getLimitString(String SQL、int offset、int limit){return getLimitString(sql、offset、integer.tostring(offset)、integer.tostring(lime)); } /*** SQLをPaged SQLステートメントに変え、オフセットと制限をプレースホルダーに置き換えます。 * <pre> *たとえば、mysql * dialect.getlimittring( "select * from user"、12、 ":offset"、0、 ":limit")は、ユーザー制限から * select * select * </pre> * * @param sql実際のsqlステートメント * @param offsetplace paginate stacter pagnewers pagnewers pagneプレースホルダー@returnページネーションSQLを含むプレースホルダー */パブリックストリングgetlimitstring(string sql、int offset、string offsetplaceholder、string limitplaceholder){stringbuilder stringbuilder = new StringBuilder(SQL); stringbuilder.append( "lime"); if(offset> 0){stringbuilder.append(offsetplaceholder).append( "、")。 } else {stringbuilder.append(limitplaceholder); } return stringbuilder.toString(); }}ほぼここでは、ページ全体を実装する方法を共有していますが、より重要なタスクがあります。すべてを実行したい場合は、基本的な作業が必要です。次に、ページオブジェクトのセット全体と、それが基づいている3層アーキテクチャを分析し、分析のエンティティとして製品を使用します。完全な3層アーキテクチャについて話した後、報酬は間違いなくいっぱいになります。エンティティ - > dao->サービスの順序でそれについて話しましょう。
まず、エンティティの2つの抽象エンティティクラスのベースエンティティとデータ実験を継承する必要があります。
baseentity.javaは主にページメンバー変数を配置します。それを継承した後、各エンティティはこのメンバー変数を持つことができます。
パッケージcom.store.base.secondmodel.base; java.io.serializableをインポートします。 java.util.mapをインポートします。 javax.xml.bind.annotation.xmltransientをインポートします。 org.apache.commons.lang3.stringutilsをインポートします。 org.apache.commons.lang3.builder.ReflectionToStringBuilderをインポートします。 com.fasterxml.jackson.annotation.jsonignoreをインポートします。 com.google.common.collect.mapsをインポートします。 com.store.base.model.storeuserをインポートします。 / ** *トップレベルのエンティティ * @author yiyong_wu * * @param <t> */ public abstract class baseentity <t>は、serializable {private static final long serialversionuid = 1l; / ** *タグを削除する(0:normal; 1:delete; 2:audit;) */ public static final string del_flag_normal = "0"; public static final string del_flag_delete = "1"; public static final string del_flag_audit = "2"; / ***エンティティ番号(一意の識別子)*/保護された文字列ID; / ***現在のユーザー*/保護されたStoreUser culernuser; / ***現在のエンティティページネーションオブジェクト*/保護されたページ<T>ページ; / ** *カスタムSQL(SQL識別子、SQLコンテンツ) */プライベートマップ<文字列、文字列> SQLMAP; public baseentity(){} public baseentity(string id){this(); this.id = id; } public string getId(){return id; } public void setid(string id){this.id = id; } / ***これは、Shiroの挿入更新を実行するときに呼び出され、現在のユーザー* @return* / @jsonignore @xmltransient Public Storeuser getCurrentuser(){if(currentuser == null){// currentuser = userutils.getuser(); } currenturuserを返します。 } public void setCurrentuser(storeuser culernuser){this.currentuser = culernuser; } @jsonignore @xmltransient public page <t> getPage(){if(page == null){page = new page <>(); }返信ページ; } public Page <t> setPage(Page <t>ページ){this.page = page;返信ページ。 } @jsonignore @xmltransient public Map <string、string> getsqlmap(){if(sqlmap == null){sqlmap = maps.newhashmap(); } sqlmapを返します。 } public void setSqlMap(Map <String、String> sqlmap){this.sqlmap = sqlmap; } / ** *挿入前にメソッドを実行すると、サブクラスは実装します * / public abstract void preinsert(); / ** *更新する前にメソッドを実行すると、サブクラスが実装されます */ public Abstract void preupdate(); /***新しいレコード(default:false)であるかどうか、setisnewRecord()を呼び出して新しいレコードを設定し、カスタムIDを使用します。 * trueに設定した後、挿入ステートメントは実行されることを余儀なくされます。 IDは自動的に生成されず、手動で渡す必要があります。 * @return */ public boolean getisnewRecord(){return stringutils.isblank(getId()); } / *** Global Variable Object* / @jsonignore Public Global GetGlobal(){return global.getInstance(); } / ***データベース名を取得* / @jsonignore public string getdbname(){return global.getConfig( "jdbc.type"); } @Override public String toString(){return ReflectionToStringBuilder.toString(this); }}dataEntity.java、主に更新と削除時間を保存し、ユーザーの作成、ユーザーの更新、論理削除フラグなど。
パッケージcom.store.base.secondmodel.base; Import Java.util.date; Import org.hibernate.validator.constraints.length; com.fasterxml.jackson.annotation.jsonformatをインポートします。 com.fasterxml.jackson.annotation.jsonignoreをインポートします。 com.store.base.model.storeuserをインポートします。 / **データエンティティ * @author yiyong_wu * * @param <t> */ public abstract class dataEntity <t> extends bersentity <t> {private static final long serialversionuid = 1l;保護されたStoreUser Createby。 // Creator Protected Date CreatedAte; //作成日保護されたStoreuser updateby; //アップデーター保護された日付更新済み。 //更新された日付保護された文字列delflag; //削除タグ(0:normal; 1:delete; 2:audit)public dataEntity(){super(); this.delflag = del_flag_normal; } public dataEntity(string id){super(id); } / ** *挿入前にメソッドを実行すると、手動で * / @Override public void preinsert(){// IDの制限なしuuidに、setisnewRecord()を呼び出してカスタムID // user user = userutils.getuser()を使用する必要があります。 // if(stringutils.isnotblank(user.getId())){// this.updateby = user; // this.createby = user; //} this.updatedate = new date(); this.createdate = this.updatedate; } / ** *更新する前にメソッドを実行すると、手動で * / @Override public void preupdate(){// user user = userutils.getuser(); // if(stringutils.isnotblank(user.getId())){// this.updateby = user; //} this.updatedate = new date(); } // @jsonignore public storeuser getcreateby(){return createby; } public void setcreateby(storeuser createby){this.createby = createby; } @jsonformat(pattern = "yyyy-mm-dd hh:mm:ss")public date getcreatedate(){return createdate; } public void setCreateDate(date recutedate){this.createdate = createdate; } // @jsonignore public storeuser getUpdateby(){return updateby; } public void setupdateby(storeuser updateby){this.updateby = updateby; } @jsonformat(pattern = "yyyy-mm-dd hh:mm:ss")public date getupdatedate(){return updatedate; } public void setupdatedate(date updatedate){this.updatedate = updatedate; } @jsonignore @length(min = 1、max = 1)public string getdelflag(){return delflag; } public void setDelfLag(string delflag){this.delflag = delflag; }}Product.java製品カテゴリ
パッケージcom.store.base.secondmodel.pratice.model; com.store.base.secondmodel.base.dataentityをインポートします。 / ***製品の基本クラス*2016年10月11日*yiyong_wu*/ public class products dataentity <product> {private static final long serialversionuid = 1l; Private String ProductName;プライベートフロート価格。 Private String Productno; public String getProductName(){return crowtName; } public void setProductName(string productName){this.productname = crowtName; } public float getPrice(){return price; } public void setprice(float frice){this.price = fith; } public string getProductno(){return grotsno; } public void setProductno(string productno){this.productno = productno; }}それはどうですか?非常に複雑なエンティティ相続関係がありますか?しかし、何がありますか?複雑になればなるほど、完全になります。次に、洗礼を受ける準備ができているレイヤー、同じ3つのレイヤーを見ます
Basedao.java予約インターフェイス
パッケージcom.store.base.secondmodel.base; / ** *最大のDAOインターフェース * @Author Yiyong_Wu * */ public Interface Basedao {} cruddao.java追加、削除、修正、クエリ[Java]プレーンコピープリントを表示するためのDAOインターフェイスレイヤー?コードフラグメントパッケージcom.store.scondmodel.baseに派生したコードでコードフラグメントを表示します。 java.util.listをインポートします。 / ** *追加、削除、修正、クエリのDAOインターフェイスを定義します * @author yiyong_wu * * @param <t> */ public interface cruddao <t> extendsao {/ ** * @param id * @return */ public t get(string id); / ** *単一のデータを取得 * @param entity * @return */ public t get(t entity); /***データリストをクエリします。ページングが必要な場合は、次のようなページングオブジェクトを設定してください。Entity.setPage(new Page <T>()); * @param entity * @return */ public list <t> findlist(t entity); / ** *すべてのデータリスト * @param entity * @return */ public list <t> findalllist(t entity); /***クエリすべてのデータリスト* @see public List <t> findalllist(t entity)* @return public list <t> findalllist(); *// ** *データを挿入 * @param entity * @return */ public int insert(t entity); / ** *データを更新 * @param entity * @return */ public int update(t entity); / ** *削除データ(通常は論理削除、DEL_FLAGフィールドを1に更新) / ** *データを削除します(通常は論理削除、DEL_FLAGフィールドを1に更新) }ProductDao.java MyBatis対応するインターフェイスマッパーもDAOの実装です。 Annotation @MyBatisRepositoryをカスタマイズする必要があります
パッケージcom.store.base.secondmodel.pratice.dao; com.store.base.secondmodel.base.cruddaoをインポートします。 com.store.base.secondmodel.base.mybatisrepositoryをインポートします。 com.store.base.secondmodel.pratice.model.productをインポートします。 / ** *todo *2016年10月11日 *yiyong_wu */ @mybatisrepositoryパブリックインターフェイスproductdaoはcruddao <product> {}を拡張しますカスタム注釈mybatisrepository.javaは、カスタムアノテーションに関連しています。ここではあまり説明しません。オンライン情報がたくさんあります。
パッケージcom.store.base.secondmodel.base; java.lang.annotation.documentedをインポートします。 java.lang.annotation.retentionをインポートします。 java.lang.annotation.targetをインポートします。 java.lang.annotation.retentionPolicyをインポートします。 java.lang.annotation.ElementTypeをインポートします。 org.springframework.stereotype.componentをインポートします。 /*** {@link org.mybatis.spring.mapper.mapperscannerconfigurer}のスキャンを容易にするために、mybatisのDAOを特定します。 * *スプリング構成ファイルで注釈付きクラスをスキャンするように構成を構成することに注意してください * *<bean id = "mapperscannerconfigurer"> *<property name = "sqlsessionfactory" /> *<プロパティname = "basepackage" balue = "com.store.ber.base.bease.base.secondel" name = "AnnotationClass" value = "com.store.base.secondmodel.base.mybatisRepository"/> * </bean> * @author yiyong_wu * */@retention(retentionPolicy.runtime)@terget(elementtype.type) ""; }注:ProductDao.javaと強力な接続を持つProductMapper.xmlファイルは、ProductMapper.xmlファイルです。上記の構成ファイルの名前空間がこのDAOへのパスを指していることがわかります。
次に、最終的なサービス分析を入力すると、3層の継承でもあります。
baseservice.java
パッケージcom.store.base.secondmodel.base; org.slf4j.loggerをインポートします。 org.slf4j.loggeractoryをインポートします。 org.slf4j.loggeractoryをインポートします。 Import org.springframework.transaction.annotation.transactional; / ** *トップレベルの親クラスのサービス * @author yiyong_wu * */ @transactional(readonly = true)public abstract class baseService {// protected logger logger = loggerfactory.getLogger(getClass()); }crudservice.java関連のビジネスインターフェイスの実装
パッケージcom.store.base.secondmodel.base; java.util.listをインポートします。 Import org.springframework.beans.factory.annotation.autowired; Import org.springframework.transaction.annotation.transactional; / ** *サービスベースクラスの追加、削除、変更、およびチェック * @author yiyong_wu * * @param <d> * @param <t> */ public abstract class crudservice <dはcruddao <t>を拡張します。 / ** *単一のデータを取得 * @param id * @return */ public t get(string id){return dao.get(id); } /** * Get a single piece of data* @param entity * @return */ public T get(T entity) { return dao.get(entity); } /** * Query list data* @param entity * @return */ public List<T> findList(T entity) { return dao.findList(entity); } /** * Query paging data* @param page paging object* @param entity * @return */ public Page<T> findPage(Page<T> page, T entity) { entity.setPage(page); page.setList(dao.findList(entity)); return page; } /** * Save data (insert or update) * @param entity */ @Transactional(readOnly = false) public void save(T entity) { if (entity.getIsNewRecord()){ entity.preInsert(); dao.insert(entity); }else{ entity.preUpdate(); dao.update(entity); } } /** * Delete data* @param entity */ @Transactional(readOnly = false) public void delete(T entity) { dao.delete(entity); }}ProductService.java,去继承CrudService接口,注意起注入dao和实体类型的一种模式
package com.store.base.secondmodel.pratice.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.store.base.secondmodel.base.CrudService; import com.store.base.secondmodel.pratice.dao.ProductDao; import com.store.base.secondmodel.pratice.model.Product; /** *TODO *2016年10月11日*yiyong_wu */ @Service @Transactional(readOnly = true) public class ProductService extends CrudService<ProductDao,Product>{ }我想看到这里的同志已经很不耐烦了。但是如果你错过接下去的一段,基本上刚才看的就快等于白看了,革命的胜利就在后半段,因为整个分页功能围绕的就是一个Page对象,重磅内容终于要出来了,当你把Page对象填充到刚才那个BaseEntity上的时候,你会发现一切就完整起来了,废话不多说,Page对象如下
package com.store.base.secondmodel.base; import java.io.Serializable; java.util.arraylistをインポートします。 java.util.listをインポートします。 import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonIgnore; import com.store.base.secondmodel.base.util.CookieUtils; import com.store.base.secondmodel.base.util.StringUtils; /** * Pagination class* @author yiyong_wu * * @param <T> */ public class Page<T> implements Serializable{ private static final long serialVersionUID = 1L; private int pageNo = 1; // Current page number private int pageSize = Integer.parseInt(Global.getConfig("page.pageSize")); // Page size, set to "-1" means that no paging is performed (paging is invalid) private long count;// Total number of records, set to "-1" means that the total number is not queried private int first;// Home page index private int last;// Last page index private int prev;// Previous page index private int next;// Next page index private boolean firstPage;// Whether it is the first page private boolean lastPage;// Whether it is the last page private int length = 6;// Display page length private int slider = 1;// Display page length before and after private List<T> list = new ArrayList<>(); private String orderBy = ""; // Standard query is valid, example: updated desc, name asc private String funcName = "page"; // Set the name of the js function called by clicking on the page number. The default is page, and it is used when there are multiple paging objects on a page. private String funcParam = ""; // Additional parameter of the function, the third parameter value. private String message = ""; // Set the prompt message, displayed after "n total number of public Page() { this.pageSize = -1; } /** * Constructor method * @param request Pass the repage parameter to remember the page number * @param response is used to set cookies, remember the page number */ public Page(HttpServletRequest request, HttpServletResponse response){ this(request, response, -2); } /** * Constructor method * @param request Pass the repage parameter to remember the page number * @param response is used to set cookies, remember the page number * @param defaultPageSize The default paging size, if -1 is passed, it is not paged, and all data is returned */ public Page(HttpServletRequest request, HttpServletResponse response, int defaultPageSize){ // Set page number parameters (pass repage parameter to remember page number) String no = request.getParameter("pageNo"); if (StringUtils.isNumeric(no)){ CookieUtils.setCookie(response, "pageNo", no); this.setPageNo(Integer.parseInt(no)); }else if (request.getParameter("repage")!=null){ no = CookieUtils.getCookie(request, "pageNo"); if (StringUtils.isNumeric(no)){ this.setPageNo(Integer.parseInt(no)); } } // Set the page size parameter (pass the repage parameter to remember the page size) String size = request.getParameter("pageSize"); if (StringUtils.isNumeric(size)){ CookieUtils.setCookie(response, "pageSize", size); this.setPageSize(Integer.parseInt(size)); }else if (request.getParameter("repage")!=null){ no = CookieUtils.getCookie(request, "pageSize"); if (StringUtils.isNumeric(size)){ this.setPageSize(Integer.parseInt(size)); } }else if (defaultPageSize != -2){ this.pageSize = defaultPageSize; } // Set the sorting parameters String orderBy = request.getParameter("orderBy"); if (StringUtils.isNotBlank(orderBy)){ this.setOrderBy(orderBy); } } /** * Constructor* @param pageNo Current page number* @param pageSize Pagination size*/ public Page(int pageNo, int pageSize) { this(pageNo, pageSize, 0); } /** * Constructor* @param pageNo Current page number* @param pageSize Pagination size* @param count Number of data strips*/ public Page(int pageNo, int pageSize, long count) { this(pageNo, pageSize, count, new ArrayList<T>()); } /** * Constructor* @param pageNo Current page number* @param pageSize Page size* @param count Number of data strips* @param list Data object list on this page*/ public Page(int pageNo, int pageSize, long count, List<T> list) { this.setCount(count); this.setPageNo(pageNo); this.pageSize = pageSize; this.list = list; } /** * Initialization parameter*/ public void initialize(){ //1 this.first = 1; this.last = (int)(count / (this.pageSize < 1 ? 20 : this.pageSize) + first - 1); if (this.count % this.pageSize != 0 || this.last == 0) { this.last++; } if (this.last < this.first) { this.last = this.first; } if (this.pageNo <= 1) { this.pageNo = this.first; this.firstPage=true; } if (this.pageNo >= this.last) { this.pageNo = this.last; this.lastPage=true; } if (this.pageNo < this.last - 1) { this.next = this.pageNo + 1; } else { this.next = this.last; } if (this.pageNo > 1) { this.prev = this.pageNo - 1; } else { this.prev = this.first; } //2 if (this.pageNo < this.first) {// If the current page is smaller than the home page this.pageNo = this.first; } if (this.pageNo > this.last) {// If the current page is larger than the last page this.pageNo = this.last; } } /** * Default output current paging tag* <div>${page}</div> */ @Override public String toString() { StringBuilder sb = new StringBuilder(); if (pageNo == first) {// If it is the home page sb.append("<li class=/"disabled/"><a href=/"javascript:/">« Previous page</a></li>/n"); } else { sb.append("<li><a href=/"javascript:/" onclick=/""+funcName+"("+prev+","+pageSize+",'"+funcParam+"');/">« Previous page</a></li>/n"); } int begin = pageNo - (length / 2); if (begin < first) { begin = first; } int end = begin + length - 1; if (end >= last) { end = last; begin = end - length + 1; if (begin < first) { begin = first; } } if (begin > first) { int i = 0; for (i = first; i < first + slider && i < begin; i++) { sb.append("<li><a href=/"javascript:/" onclick=/""+funcName+"("+i+","+pageSize+",'"+funcParam+"');/">" + (i + 1 - first) + "</a></li>/n"); } if (i < begin) { sb.append("<li class=/"disabled/"><a href=/"javascript:/">...</a></li>/n"); } } for (int i = begin; i <= end; i++) { if (i == pageNo) { sb.append("<li class=/"active/"><a href=/"javascript:/">" + (i + 1 - first) + "</a></li>/n"); } else { sb.append("<li><a href=/"javascript:/" onclick=/"+funcName+"("+i+","+pageSize+",'"+funcParam+"');/">" + (i + 1 - first) + "</a></li>/n"); } } if (last - end > slider) { sb.append("<li class=/"disabled/"><a href=/"javascript:/">...</a></li>/n"); end = last - slider; } for (int i = end + 1; i <= last; i++) { sb.append("<li><a href=/"javascript:/" onclick=/"+funcName+"("+i+","+pageSize+",'"+funcParam+"');/">" + (i + 1 - first) + "</a></li>/n"); } if (pageNo == last) { sb.append("<li class=/"disabled/"><a href=/"javascript:/">Next page»</a></li>/n"); } else { sb.append("<li><a href=/"javascript:/" onclick=/""+funcName+"("+next+","+pageSize+",'"+funcParam+"');/">" + "next page»</a></li>/n"); } return sb.toString(); } /** * Get pagination HTML code* @return */ public String getHtml(){ return toString(); } /** * Get the total number of settings* @return */ public long getCount() { return count; } /** * Set the total number of data* @param count */ public void setCount(long count) { this.count = count; if (pageSize >= count){ pageNo = 1; } } /** * Get the current page number* @return */ public int getPageNo() { return pageNo; } /** * Set the current page number* @param pageNo */ public void setPageNo(int pageNo) { this.pageNo = pageNo; } /** * Get the page size* @return */ public int getPageSize() { return pageSize; } /** * Set page size (maximum 500) // > 500 ? 500 : pageSize; * @param pageSize */ public void setPageSize(int pageSize) { this.pageSize = pageSize <= 0 ? 10 : pageSize; } /** * Home page index* @return */ @JsonIgnore public int getFirst() { return first; } /** * Last page index* @return */ @JsonIgnore public int getLast() { return last; } /** * Get the total number of pages* @return getLast(); */ @JsonIgnore public int getTotalPage() { return getLast(); } /** * Is it the first page* @return */ @JsonIgnore public boolean isFirstPage() { return firstPage; } /** * Is it the last page* @return */ @JsonIgnore public boolean isLastPage() { return lastPage; } /** * Previous page index value* @return */ @JsonIgnore public int getPrev() { if (isFirstPage()) { return pageNo; } else { return pageNo - 1; } } /** * Next page index value* @return */ @JsonIgnore public int getNext() { if (isLastPage()) { return pageNo; } else { return pageNo + 1; } } /** * Get the data object list of this page* @return List<T> */ public List<T> getList() { return list; } /** * Set the data object list of this page* @param list */ public Page<T> setList(List<T> list) { this.list = list; initialize();これを返します。 } /** * Get query sorting string* @return */ @JsonIgnore public String getOrderBy() { // SQL filtering to prevent injection of String reg = "(?:')|(?:--)|(//*(?:.|[//n//r])*?//*/)|" + "(//b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)//b)"; Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); if (sqlPattern.matcher(orderBy).find()) { return ""; } return orderBy; } /** * Set query sorting, standard query is valid, Example: updated desc, name asc */ public void setOrderBy(String orderBy) { this.orderBy = orderBy; } /** * Get the name of the js function called by the click page number* function ${page.funcName}(pageNo){location="${ctx}/list-${category.id}${urlSuffix}?pageNo="+i;} * @return */ @JsonIgnore public String getFuncName() { return funcName; } /** * Set the name of the js function called by the click page number. The default is page, which is used when there are multiple paging objects on a page. * @param funcName Default is page */ public void setFuncName(String funcName) { this.funcName = funcName; } /** * Get additional parameters of the pagination function* @return */ @JsonIgnore public String getFuncParam() { return funcParam; } /** * Set additional parameters of the pagination function* @return */ public void setFuncParam(String funcParam) { this.funcParam = funcParam; } /** * Set the prompt message, displayed after "n total numbers"* @param message */ public void setMessage(String message) { this.message = message; } /** * Is the pagination valid* @return this.pageSize==-1 */ @JsonIgnore public boolean isDisabled() { return this.pageSize==-1; } /** * Whether to count the total number* @return this.count==-1 */ @JsonIgnore public boolean isNotCount() { return this.count==-1; } /** * Get Hibernate FirstResult */ public int getFirstResult() { int firstResult = (getPageNo() - 1) * getPageSize(); if (firstResult >= getCount()) { firstResult = 0; } return firstResult; } /** * Get Hibernate MaxResults */ public int getMaxResults(){ return getPageSize(); }}看完这个Page对象应该稍微有点感觉了吧,然后我在胡乱贴一些相关用到的工具类吧,工具类的话我只稍微提一下,具体大家可以弄到自己的代码上好好解读。
PropertiesLoader.java 用来获取resource文件夹下的常量配置文件
package com.store.base.secondmodel.base.util; import java.io.IOException; import java.io.InputStream; import java.util.NoSuchElementException; import java.util.Properties; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; /** * Properties file loading tool class. Multiple properties files can be loaded, * The value of the same attribute in the last loaded file will overwrite the previous value, but System's Property takes precedence. * @author yiyong_wu * */ public class PropertiesLoader { private static Logger logger = LoggerFactory.getLogger(PropertiesLoader.class); private static ResourceLoader resourceLoader = new DefaultResourceLoader(); private final Properties properties; public PropertiesLoader(String... resourcesPaths) { properties = loadProperties(resourcesPaths); } public Properties getProperties() { return properties; } /** * Take out the Property, but System's Property takes priority, and the empty string cannot be returned. */ private String getValue(String key) { String systemProperty = System.getProperty(key); if (systemProperty != null) { return systemProperty; } if (properties.containsKey(key)) { return properties.getProperty(key); } 戻る ""; } /** * Take out the String property, but System's Property takes priority. If all are Null, an exception will be thrown. */ public String getProperty(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return value; } /** * Take out the Property of type String, but the Property of the System is preferred. If it is Null, the Default value will be returned. */ public String getProperty(String key, String defaultValue) { String value = getValue(key); return value != null ? value : defaultValue; } /** * Take out the Property of type Integer, but the Property of the System is preferred. If it is Null or the content is wrong, an exception will be thrown. */ public Integer getInteger(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return Integer.valueOf(value); } /** * Take out the Integer type Property, but the System's Property takes priority. If all are Null, the Default value will be returned, and an exception will be thrown if the content is wrong*/ public Integer getInteger(String key, Integer defaultValue) { String value = getValue(key); return value != null ? Integer.valueOf(value) : defaultValue; } /** * Take out the Double type Property, but the System's Property is preferred. If all are Null or the content is wrong, an exception will be thrown. */ public Double getDouble(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return Double.valueOf(value); } /** * Take out the Double type Property, but the System's Property is preferred. If all are Null, a Default value will be returned. If all are Null, an exception will be thrown. */ public Double getDouble(String key, Integer defaultValue) { String value = getValue(key); return value != null ? Double.valueOf(value) : defaultValue.doubleValue(); } /** * Take out the Property of Boolean type, but the Property of the System is preferred. If all exceptions are thrown for Null, if the content is not true/false, it will return false. */ public Boolean getBoolean(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return Boolean.valueOf(value); } /** * Take out the Boolean type Property, but System's Property takes priority. If all are Null, return the Default value, and if the content is not true/false, return false. */ public Boolean getBoolean(String key, boolean defaultValue) { String value = getValue(key); return value != null ? Boolean.valueOf(value) : defaultValue; } /** * Load multiple files, and the file path uses Spring Resource format. */ private Properties loadProperties(String... resourcesPaths) { Properties props = new Properties(); for (String location : resourcesPaths) { InputStream is = null; try { Resource resource = resourceLoader.getResource(location); is = resource.getInputStream(); props.load(is); } catch (IOException ex) { logger.error("Could not load properties from path:" + location , ex); } finally { IOUtils.closeQuietly(is); } } return props; }}Global.java 用来获取全局的一些常量,可以是从配置文件中读取的常量,也可以是定义成final static的常量,获取配置文件的话是调用上面那个类进行获取的。
package com.store.base.secondmodel.base; import java.io.File; import java.io.IOException; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.DefaultResourceLoader; import com.google.common.collect.Maps; import com.store.base.secondmodel.base.util.PropertiesLoader; import com.store.base.secondmodel.base.util.StringUtils; /** * Global configuration class* @author yiyong_wu * */ public class Global { private static final Logger logger = LoggerFactory.getLogger(Global.class); /** * Current object instance*/ private static Global global = new Global(); /** * Save global attribute value*/ private static Map<String, String> map = Maps.newHashMap(); /** * Properties file loading object*/ private static PropertiesLoader loader = new PropertiesLoader("application.properties"); /** * Show/hide public static final String SHOW = "1"; public static final String HIDE = "0"; /** * Yes/No*/ public static final String YES = "1"; public static final String NO = "0"; /** * Status up/down app dedicated*/ public static final String UPSHVELF = "1"; public static final String DOWNSHVELF = "2"; public static final String SEPARATOR = "/"; /** * True/Wrong*/ public static final String TRUE = "true"; public static final String FALSE = "false"; /** * Basic virtual path of uploading file*/ public static final String USERFILES_BASE_URL = "/userfiles/"; /** * For rich text editors, empty divs will be generated at the end */ public static final String ENDS = "<p><br></p>"; /** * Default empty private constructor*/ public Global() { //do nothing in this method,just empty } /** * Get the current object instance*/ public static Global getInstance() { return global; } /** * Get the configuration*/ public static String getConfig(String key) { String value = map.get(key); if (value == null){ value = loader.getProperty(key); map.put(key, value != null ? value : StringUtils.EMPTY); } return value; } /** * Get URL suffix*/ public static String getUrlSuffix() { return getConfig("urlSuffix"); } /** * Page get constant* @see ${fns:getConst('YES')} */ public static Object getConst(String field) { try { return Global.class.getField(field).get(null); } catch (Exception e) { logger.error("Error getting constant", e); } nullを返します。 } /** * Get project path* @return */ public static String getProjectPath(){ // If the project path is configured, it will be returned directly, otherwise it will be automatically retrieved. String projectPath = Global.getConfig("projectPath"); if (StringUtils.isNotBlank(projectPath)){ return projectPath; } try { File file = new DefaultResourceLoader().getResource("").getFile(); if (file != null){ while(true){ File f = new File(file.getPath() + File.separator + "src" + File.separator + "main"); if (f == null || f.exists()){ break; } if (file.getParentFile() != null){ file = file.getParentFile(); }else{ break; } } projectPath = file.toString(); } } catch (IOException e) { logger.error("Loading configuration file failed", e); } return projectPath; }}}CookieUtil.java 从名称就知道是针对获取和存储cookie的一个工具类
package com.store.base.secondmodel.base.util; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Cookie tool class * @author yiyong_wu * */ public class CookieUtils { private static final Logger logger = LoggerFactory.getLogger(CookieUtils.class); /** * Private constructor */ private CookieUtils() { } /** * Set Cookie (generated time is 1 year) * @param name Name * @param value Value */ public static void setCookie(HttpServletResponse response, String name, String value) { setCookie(response, name, value, 60*60*24*365); } /** * Set Cookie * @param name Name * @param value Value * @param maxAge Survival time (units of seconds) * @param uri Path */ public static void setCookie(HttpServletResponse response, String name, String value, String path) { setCookie(response, name, value, path, 60*60*24*365); } /** * Set Cookie * @param name Name * @param value Value * @param maxAge Survival time (units of seconds) * @param uri path */ public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) { setCookie(response, name, value, "/", maxAge); } /** * Set Cookie * @param name Name* @param value Value* @param maxAge Survival time (in seconds) * @param uri path */ public static void setCookie(HttpServletResponse response, String name, String value, String path, int maxAge) { Cookie cookie = new Cookie(name, null); cookie.setPath(path); cookie.setMaxAge(maxAge); try { cookie.setValue(URLEncoder.encode(value, "utf-8")); } catch (UnsupportedEncodingException e) { logger.error("Unsupported encoding", e); } response.addCookie(cookie); } /** * Get the value of the specified cookie* @param name* @return value*/ public static String getCookie(HttpServletRequest request, String name) { return getCookie(request, null, name, false); } /** * Get the value of the specified cookie and delete it. * @param name name* @return value*/ public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name) { return getCookie(request, response, name, true); } /** * Get the value of the specified cookie* @param request Request object* @param response Response object* @param name* @param isRemove Whether to remove* @return value*/ public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name, boolean isRemove) { String value = null; Cookie[] cookies = request.getCookies(); if(cookies == null) { return value; } for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { try { value = URLDecoder.decode(cookie.getValue(), "utf-8"); } catch (UnsupportedEncodingException e) { logger.error("UnsupportedEncoding", e); } if (isRemove) { cookie.setMaxAge(0); response.addCookie(cookie); } } return value; }}}SpringContextHolder.java 主要是用来在java代码中获取当前的ApplicationContext,需要在spring配置文件中配置这个bean并且懒加载设置成false;
package com.store.base.secondmodel.base.util; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @Service @Lazy(false) public class SpringContextHolder implements ApplicationContextAware, DisposableBean { private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class); private static ApplicationContext applicationContext = null; /** * Get the ApplicationContext stored in a static variable. */ public static ApplicationContext getApplicationContext() { assertContextInjected(); return applicationContext; } /** * Get the bean from the static variable applicationContext and automatically transform it into the type of the assigned object. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } /** * Get the bean from the static variable applicationContext and automatically transform it into the type of the assigned object. */ public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } @Override public void destroy() throws Exception { SpringContextHolder.clearHolder(); } /** * Implement the ApplicationContextAware interface and inject the Context into a static variable. */ @Override public void setApplicationContext(ApplicationContext applicationContext) { logger.debug("Inject ApplicationContext to SpringContextHolder:{}", applicationContext); SpringContextHolder.applicationContext = applicationContext; if (SpringContextHolder.applicationContext != null) { logger.info("The ApplicationContext in SpringContextHolder is overwritten, the original ApplicationContext is:" + SpringContextHolder.applicationContext); } } /** * Clear the ApplicationContext in SpringContextHolder to Null. */ public static void clearHolder() { if (logger.isDebugEnabled()){ logger.debug("Clear ApplicationContext in SpringContextHolder:" + applicationContext); } applicationContext = null; } /** * Check that the ApplicationContext is not empty. */ private static void assertContextInjected() { Validate.validState(applicationContext != null, "The applicaitonContext property is not injected, please define SpringContextHolder in applicationContext.xml."); }}StringUtils.java字符串相关的一个工具类
package com.store.base.secondmodel.base.util; import java.io.UnsupportedEncodingException; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.LocaleResolver; import com.store.base.util.Encodes; /** * String help class* @author yiyong_wu * */ public class StringUtils extends org.apache.commons.lang3.StringUtils { private static final char SEPARATOR = '_'; private static final String CHARSET_NAME = "UTF-8"; private static final Logger logger = LoggerFactory.getLogger(StringUtils.class); /** * Convert to byte array* @param str * @return */ public static byte[] getBytes(String str){ if (str != null){ try { return str.getBytes(CHARSET_NAME); } catch (UnsupportedEncodingException e) { logger.error("", e); return new byte[0]; } }else{ return new byte[0]; } } /** * Convert to byte array* @param str * @return */ public static String toString(byte[] bytes){ try { return new String(bytes, CHARSET_NAME); } catch (UnsupportedEncodingException e) { logger.error("", e); return EMPTY; } } /** * Does it contain strings* @param str Verification string* @param strs String group* @return contains return true */ public static boolean inString(String str, String... strs){ if (str != null){ for (String s : strs){ if (str.equals(trim(s))){ return true; } } } return false; } /** * Replace HTML tag method*/ public static String replaceHtml(String html) { if (isBlank(html)){ return ""; } String regEx = "<.+?>"; Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(html); return m.replaceAll(""); } /** * Replace with HTML recognized by the phone, remove the style and attributes, and keep Enter. * @param html * @return */ public static String replaceMobileHtml(String html){ if (html == null){ return ""; } return html.replaceAll("<([az]+?)//s+?.*?>", "<$1>"); } /** * Replace with HTML recognized by the phone, remove the style and attributes, and keep Enter. * @param txt * @return */ public static String toHtml(String txt){ if (txt == null){ return ""; } return replace(replace(Encodes.escapeHtml(txt), "/n", "<br/>"), "/t", " "); } /** * Thumbnail string (not distinguishing between Chinese and English characters) * @param str Target string* @param length Intercept length* @return */ public static String abbr(String str, int length) { if (str == null) { return ""; } try { StringBuilder sb = new StringBuilder(); int currentLength = 0; for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) { currentLength += String.valueOf(c).getBytes("GBK").length; if (currentLength <= length - 3) { sb.append(c); } else { sb.append("...");壊す; }} return sb.toString(); } catch (UnsupportedEncodingException e) { logger.error("", e); } 戻る ""; } /** * Convert to Double type*/ public static Double toDouble(Object val){ if (val == null){ return 0D; } try { return Double.valueOf(trim(val.toString())); } catch (Exception e) { logger.error("", e); return 0D; } } /** * Convert to Float type*/ public static Float toFloat(Object val){ return toDouble(val).floatValue(); } /** * Convert to Long type*/ public static Long toLong(Object val){ return toDouble(val).longValue(); } /** * Convert to Integer type*/ public static Integer toInteger(Object val){ return toLong(val).intValue(); } /** * Get i18n string*/ public static String getMessage(String code, Object[] args) { LocaleResolver localLocaleResolver = SpringContextHolder.getBean(LocaleResolver.class); HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); Locale localLocale = localLocaleResolver.resolveLocale(request); return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale); } /** * Get the user remote address*/ public static String getRemoteAddr(HttpServletRequest request){ String remoteAddr = request.getHeader("X-Real-IP"); if (isNotBlank(remoteAddr)) { remoteAddr = request.getHeader("X-Forwarded-For"); } if (isNotBlank(remoteAddr)) { remoteAddr = request.getHeader("Proxy-Client-IP"); } if (isNotBlank(remoteAddr)) { remoteAddr = request.getHeader("WL-Proxy-Client-IP"); } return remoteAddr != null ? remoteAddr : request.getRemoteAddr(); } /** * Camel nomenclature tool* @return * toCamelCase("hello_world") == "helloWorld" * toCapitalizeCamelCase("hello_world") == "HelloWorld" * toUnderScoreCase("helloWorld") = "hello_world" */ public static String toCamelCase(String s) { String s1 =s; if (s1 == null) { return null; } s1 = s.toLowerCase(); StringBuilder sb = new StringBuilder(s1.length()); boolean upperCase = false; for (int i = 0; i < s1.length(); i++) { char c = s1.charAt(i); if (c == SEPARATOR) { upperCase = true; } else if (upperCase) { sb.append(Character.toUpperCase(c)); upperCase = false; } else { sb.append(c); }} return sb.toString(); } /** * Camel nomenclature tool* @return * toCamelCase("hello_world") == "helloWorld" * toCapitalizeCamelCase("hello_world") == "HelloWorld" * toUnderScoreCase("helloWorld") = "hello_world" */ public static String toCapitalizeCamelCase(String s) { String s1 = s; if (s1 == null) { return null; } s1 = toCamelCase(s1); return s1.substring(0, 1).toUpperCase() + s1.substring(1); } /** * Camel Nomenclature Tool* @return * toCamelCase("hello_world") == "helloWorld" * toCapitalizeCamelCase("hello_world") == "HelloWorld" * toUnderScoreCase("helloWorld") = "hello_world" */ public static String toUnderScoreCase(String s) { if (s == null) { return null; } StringBuilder sb = new StringBuilder(); boolean upperCase = false; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); boolean nextUpperCase = true; if (i < (s.length() - 1)) { nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); } if ((i > 0) && Character.isUpperCase(c)) { if (!upperCase || !nextUpperCase) { sb.append(SEPARATOR); } upperCase = true; } else { upperCase = false; } sb.append(Character.toLowerCase(c)); } return sb.toString(); } /** * 转换为JS获取对象值,生成三目运算返回结果* @param objectString 对象串* 例如:row.user.id * 返回:!row?'':!row.user?'':!row.user.id?'':row.user.id */ public static String jsGetVal(String objectString){ StringBuilder result = new StringBuilder(); StringBuilder val = new StringBuilder(); String[] vals = split(objectString, "."); for (int i=0; i<vals.length; i++){ val.append("." + vals[i]); result.append("!"+(val.substring(1))+"?'':"); } result.append(val.substring(1)); return result.toString(); }}有了上面这些基础的东西,只需要在写一个控制层接口,就可以看到每次返回一个page对象,然后里面封装好了查询对象的列表,并且是按分页得出列表。
package com.store.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.store.base.secondmodel.base.Page; import com.store.base.secondmodel.pratice.model.Product; import com.store.base.secondmodel.pratice.service.ProductService; /** *TODO *2016年10月11日*yiyong_wu */ @RestController @RequestMapping("/product") public class ProductController { @Autowired private ProductService productService; @ResponseBody @RequestMapping(value="/getPageProduct") public Page<Product> getPageProduct(HttpServletRequest request,HttpServletResponse response){ Page<Product> page = productService.findPage(new Page<Product>(request,response), new Product()); return page; } }最后在看一下页面怎么使用这个page对象,这样我们就完整地介绍了这个一个分页功能,代码很多,但很完整。
<%@ page contentType="text/html;charset=UTF-8"%> <%@ include file="/WEB-INF/views/include/taglib.jsp"%> <html> <head> <title></title> <meta name="decorator" content="default" /> function page(n, s) { if (n) $("#pageNo").val(n); if (s) $("#pageSize").val(s); $("#searchForm").attr("action", "${ctx}/app/bank/list"); $("#searchForm").submit(); return false; } </script> </head> <body> <form:form id="searchForm" modelAttribute="XXXX" action="${ctx}/XXX" method="post"> <input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}" /> <input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}" /> <ul> <li> <label>是否上架:</label> <form:select id="status" path="status"> <form:option value="" label=""/> <form:options items="${fns:getDictList('yes_no_app')}" itemLabel="label" itemValue="value" htmlEscape="false"/> </form:select> </li> <li><input id="btnSubmit" type="submit" value="查询"/> <li></li> </ul> </form:form> <sys:message content="${message}" /> <sys:message content="${message}" /> <table id="contentTable"> <thead> <tr> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> </tr> </thead> <tbody> <c:forEach items="${page.list}" var="XXXX"> <tr> <td>${XXXX.name}</td> <td><a href="${ctx}/app/bank/form?id=${XXXX.id}">${XXXX.}</a></td> <td>${XXXX.}</td> <td>${XXXX.}</td> <td>${XXXX.}</td> <td>${fns:getDictLabel(XXXX.isHot, 'yes_no_app', '无')}</td> <td>${XXXX.}</td> <td><c:if test="${XXXX.status==1 }">上架</c:if> <c:if test="${XXXX.status==2 }">下架</c:if> </td> </tr> </c:forEach> </tbody> </table> <div>${page} <li style="padding-top: 6px;padding-left: 12px;float: left;">共${page.count}条</li></div> </body> </html>到这里就基本上把整个分页功能描述得比较清楚了,希望可以帮助到你们快速解决分页这个问题,当然要在前端显示分页漂亮的话要针对li做一些css样式啥的,最后祝福你可以快速掌握这个分页功能!
以上所述是小编给大家介绍的Mybatis常用分页插件实现快速分页处理技巧,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!