قبل مشاركة رمز التنفيذ لصفحة الاستعلام بأكملها ، فهم عملية التنفيذ أولاً.
1. بشكل عام ، يستخدم اعتراض المكون الإضافي MyBatis لاعتراضه قبل تنفيذ SQL ، وإضافة LIME XX إلى بيان الاستعلام
2. استخدم كائن صفحة لتشغيله خلال عملية التنفيذ بأكملها. يتطلب كائن هذه الصفحة كتابة مكونات ترقيم الصفحات الأمامية في Java.
3. استخدم مجموعة كاملة نسبيًا من الكيان المكون من ثلاث طبقات ، و DAO ، وخدمة لدعم بنية الصفحات هذه
4. بعض الفئات المساعدة المستخدمة في هذه الصفحة
ملاحظة: هناك الكثير من المحتوى المشترك. لن أدرج الجرار المطلوبة واحدة تلو الأخرى. عند استخدام وظيفة ترقيم الصفحات هذه ، فقط ابحث عن أي حزم جرة في الليل. استخدم حزمة Maven لاستيراد قدر الإمكان لأن Maven يمكن أن تقلل من تعارضات الإصدار وغيرها من المزايا.
لا يمكنني إلا أن أقول أنه يمكنك استخدام وظيفة الترحيل أسهل في أسرع وقت ممكن. إذا كنت لا تفهم ذلك ، فيرجى إضافتي إلى QQ ومناقشتها معًا. لا أقسم! أيضًا ، قد تكون المقالة كبيرة نسبيًا ، ولكن قراءتها بعض الوقت ، وقراءتها وممارستها ستكسب بالتأكيد الكثير.
الخطوة 1: نظرًا لأن الموضوع يدور حول كيفية التراجع ، فلنبدأ بـ MyBatis. أولاً ، سنأخذ ملفين تكوين أكثر أهمية متعلقة بـ MyBatis لفهم موجز. أحدهما هو mybatis-config.xml ، والآخر هو ملف تكوين Mapper المقابل للكيان. سأكتب تعليقات على ملف التكوين ، وسيفهمه الجميع في لمحة.
mybatis-config.xml
<! CONCTYPE تكوين عام "-// mybatis.org//dtd config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <! -> <setting name = "cacheenabled" value = "false"/> <!-تمكين أو تعطيل التحميل كسول على مستوى العالم. عند تعطيلها ، يتم تحميل جميع الكائنات المرتبطة على الفور. -> <setting name = "lazyloadingEnabled" value = "true"/> <!-عند تمكينه ، سيقوم كائن مع خاصية تحميل كسول بتحميل أي خاصية تمامًا عند استدعاءها. خلاف ذلك ، سيتم تحميل كل خاصية حسب الحاجة. -> <setting name = "aggressivelazyloading" value = "true"/> <!-سواء للسماح لـ SQL واحد بإرجاع مجموعات بيانات متعددة (اعتمادًا على توافق السائق) الافتراضي: TRUE-> <STETTER NAME = "MultiplerSultSetSenabled" value = "true"/> <! name = "useColumnLabel" value = "true"/> <!- اسمح JDBC بإنشاء مفاتيح أساسية. مطلوب دعم محرك الأقراص. إذا تم تعيين هذا الإعداد ، فسيؤدي هذا الإعداد إلى إجبار المفتاح الأساسي الذي تم إنشاؤه على ذلك ، فإن بعض محركات الأقراص غير متوافقة ولكن لا يزال من الممكن تنفيذها. الافتراضي: false-> <setting name = "usegeneratedKeys" value = "false"/> <!-حدد كيف يقوم MyBatis بتخطيط أعمدة قاعدة البيانات تلقائيًا لا شيء: لا تحجب الجزئي: جزء كامل: all-> <setting name = executor may extruction extruction ؛ execution may reuse can extruction ؛ عبارات وتحديثات الدُفعات)-> <Setting Name = "DefaultExecutortype" value = "Simple"/> <!-تحويل الحقول باستخدام تسميات الإبل. -> <Setting Name = "mapundersCoretOcamElcase" value = "true"/> <!-إعداد نطاق نطاق ذاكرة التخزين المؤقت المحلي: سيكون هناك بيان لمشاركة البيانات: نطاق البيانات (لن يكون هذا مشاركة البيانات) defalut: session-> <setting name = "localcachescope" value = "session"/> <! اكتب عند إدراج قيمة خالية-> <إعداد name = "jdbctypefornull" value = "null"/> <setting name = "logPrefix" value = "dao. alias = "user"> </starealias> <typealias type = "com.store.base.secondmodel.pratice.model.product اعتراض الصفحة تم تكوينه لـ MyBatis ، ونحن بحاجة إلى تنفيذ هذه الصفحة اعتراض أنفسنا -> <plugins> <plugin interceptor = "com.store.base.secondmodel.base.pageinterceptor.paginationInterceptor"/> </sults> </configuration>
يتم استخدام ProductMapper.xml ككائن اختبار ، ويقوم ملف Mapper هذا ببساطة بتكوين عبارة استعلام يجب استخدامها.
<؟ Namespace = "com.store.base.secondmodel.pratice.dao.productdao"> <sql id = "baseColumns"> id ، product_name as productname ، product_no as productNo ، السعر كسعر </sql> <select id = "findist" resultType = "com.store.base.secondmodel.pratice.model.product"> حدد <تضمين refid = "baseColumns"/> من t_store_product </select> </prapper>
الخطوة 2: بعد ذلك ، سوف نجري تحليلًا وتعلمًا متعمقًا لهذا اعتراض ترقيم الصفحات ، بما في ذلك الطبقات التالية وواجهاتها المقابلة
(1) فئة اعتراض الأساس
(2) PaginationInterceptor فئة Pagination Plugin التي نريد استخدامها ، ورث الفئة الأساسية أعلاه
(3) يستخدم SqlHelper بشكل أساسي لتنفيذ عبارات العد مقدمًا ، وأيضًا للحصول على بيان ترقيم ترقيمها بالكامل.
(4) لهجة ، mysqldialect ، تستخدم بشكل أساسي ما إذا كانت قاعدة البيانات تدعم عبارات الحد ، ثم تغلف عبارات الحد الكامل
فيما يلي عروض المشاركة لهذه الفئات
BaseInterceptor.java
package 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.replections ؛ / ** * فئة قاعدة MyBatis Pagination Interceptor * Author Yiyong_wu * */ Public Abstract Class BaseInterceptor تنفذ التقاطع ، قابلة للتسلسل {Private Static Final Long SerialVersionuid = 1L ؛ صفحة سلسلة نهائية ثابتة محمية = "صفحة" ؛ مندوب السلسلة النهائية الساكنة المحمية = "مندوب" ؛ السلسلة النهائية الثابتة المحمية medped_statement = "mappedStatement" ؛ سجل السجل المحمي = logfactory.getLog (this.getClass ()) ؛ لهجة محمية لهجة. / *** تحويل المعلمات والتحقق منها* param parameterObject parameterObjected* paginp pagination كائن* @return كائن* throws nosuchfieldexception لا يمكن العثور على المعلمة*/ suppressWarnings (uncheced ") حماية static page <objecter> confermeter. إرجاع (الصفحة <Object>) parameterObject ؛ } آخر {return (صفحة <Object>) Reflections.getFieldValue (parameterObject ، page) ؛ }} catch (استثناء e) {return null ؛ }} /*** تعيين خصائص ، ودعم فئات لهجة مخصصة وكيفية صياغة قواعد البيانات* <Code> DialectClass </code> ، فئات اللهجة المخصصة. يمكن تكوين ذلك دون تكوين * <dode> dbms </dode> نوع قاعدة البيانات ، قاعدة البيانات المدعومة بواسطة المكون الإضافي * <code> sqlpattern </code> معرف SQL الذي يجب اعتراضه * param p خصائص */itproperties void protected (الخصائص p) {depalect dialect = null ؛ String dBtype = global.getConfig ("jdbc.type") ؛ if ("mysql" .equals (dbtype)) {dialect = new mysqldialect () ؛ } if (dalect == null) {رمي new RunTimeException ("خطأ في لهجة MyBatis.") ؛ } لهجة = لهجة ؛ }}ترقيم الصفحات
package com.store.base.secondmodel.base.pageInterceptor ؛ استيراد java.util.properties ؛ استيراد org.apache.ibatis.executor.executor ؛ استيراد org.apache.ibatis.mapping.boundsql ؛ استيراد org.apache.ibatis.mapping.mappedStatement ؛ استيراد org.apache.ibatis.mapping.sqlsource ؛ استيراد org.apache.ibatis.plugin.Intercepts ؛ استيراد org.apache.ibatis.plugin.invocation ؛ استيراد org.apache.ibatis.plugin ؛ استيراد org.apache.ibatis.plugin.signature ؛ استيراد org.apache.ibatis.reflection.metaObject ؛ استيراد org.apache.ibatis.session.resulthandler ؛ استيراد org.apache.ibatis.session.rowbounds ؛ استيراد com.store.base.secondmodel.base.page ؛ استيراد com.store.base.secondmodel.base.util.stringutils ؛ استيراد com.store.base.util.replections ؛ /*** البرنامج المساعد لترحيل قاعدة البيانات ، يعترض فقط عبارات الاستعلام. * Author yiyong_wu * */ @intercepts ({signature (type = executor.class ، method = "query" ، args = {medpedStatement.class ، object.class ، rowbounds.class ، resehandler.class}) Override Public Object Intercept (Invocation Invocation) يلقي رمي {Final MedPedStatement MedpedStatement = (MedpedStatement) invocation.getargs () [0] ؛ المعلمة الكائن = invocation.getargs () [1] ؛ BODEDSQL BODEDSQL = MEDPEDSTATEMTEMT.GETBOUNDSQL (المعلمة) ؛ parameterObject = boundsql.getParameterObject () ؛ // احصل على صفحة كائن معلمة ترقيم الصفحات <Object> page = null ؛ if (parameterObject! = null) {page = convertParameter (parameterObject ، page) ؛ } // إذا تم تعيين كائن Paging ، يتم تنفيذ Paging if (page! = null && page.getPagesize ()! = -1) {if (stringUtils.IsBlank (boundsql.getsql ()))) {return null ؛ } String OriginalsQl = bONDSQL.GETSQL (). trim () ؛ // احصل على إجمالي عدد السجلات page.setCount (sqlhelper.getCount (OriginalsQl ، null ، mappedStatement ، parameterObject ، boundsql ، log)) ؛ . invocation.getargs () [2] = new RowBounds (RowBounds.no_row_offset ، rowbounds.no_row_limit) ؛ BODEDSQL NewboundSQL = New BODEDSQL (MEPTSTATEMTEMNED.GETCONFIGURATION () ، pagesql ، BONDSQL.GetParamEterMappings () ، BONDSQL.GetParameterObject ()) ؛ . Reflections.setFieldValue (newboundsql ، "metaparameters" ، mo) ؛ }. invocation.getargs () [0] = newms ؛ } return invocation.proceed () ؛ } Override Public Object Plugin (Object Target) {return plugin.wrap (target ، this) ؛ } Override public void setProperties (خصائص الخصائص) {super.initProperties (الخصائص) ؛ } private medstatement copyfrommpedStatement (MapPedStatement MS ، SqlSource NewsQlSource) {medpedStatement.Builder Builder = new MedpedStatement.builder (Ms.GetConfiguration () ، Ms.GetId () ، newsqlsource ، ms.getsqlcomnpe () ؛ 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 ()) ؛ إرجاع builder.build () ؛ } plongsqlsqlsource probedsqlsource تنفذ sqlsource {boundsql boundsql ؛ PublicsqlsqlSource (boundsql boundsql) {this.boundsql = boundsql ؛ } Override Public BODEDSQL getBoundSQL (Object parameterObject) {return boundsql ؛ }}}sqlhelper.java
package 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 ؛ استيراد org.apache.ibatis.mapping.boundsql ؛ استيراد 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 ؛ استيراد org.apache.ibatis.session.configuration ؛ استيراد org.apache.ibatis.type.typehandler ؛ استيراد 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.replections ؛ /*** SQL Tool Class* Author yiyong_wu** /public class sqlhelper { /*** default private constructor* /private sqlHelper () {} /*** اضبط القيمة لمعلمات sql (؟) ، الرجوع إلى org.ibateis.executor.parameter.defaultler**** SQL كائن البيان. * param mappedStatement medpedStatement * param boundsql sql * param parameterObjected parameterObjected athrows ParameterObject) يلقي sqlexception {errorcontext.instance (). النشاط ("المعلمات الإعداد"). كائن (mapPedStatement.getParameterMap (). getId ()) ؛ قائمة <ParmeterMapping> paramEterMappings = boundsql.getParamEterMappings () ؛ if (parameterMappings! = null) {configuration configuration = medpedStatement.getConfiguration () ؛ typeHandlerRegistry typeHandlerRegistry = configuration.getTyPeHandlerRegistry () ؛ metaObject metaObject = parameterObject == null؟ NULL: configuration.newmetaobject (parameterObject) ؛ لـ (int i = 0 ؛ i <parametermappings.size () ؛ i ++) {parameterMapping parameterMapping = parameterMappings.get (i) ؛ if (parameterMapping.getMode ()! = parametermode.out) {value object ؛ string propertyName = parameTerMapping.getProperty () ؛ PropertyTokenizer Prop = New PropertyTokenizer (PropertyName) ؛ if (parameterObject == null) {value = null ؛ } آخر إذا (typeHandlerRegistry.hastypeHandler (parameterObject.getClass ())) {value = parameterObject ؛ } if if (boundsql.hasadditionalparameter (propertyName)) {value = boundsql.getAdditionalParameter (propertyName) ؛ } if if (propertyName.StartSwith (foreachsqlnode.item_prefix) && bONDSQL.HasAdditionalParameter (prop.getName ())) {value = boundsql.getAdditionalParameter (prop.getName ()) ؛ if (value! = null) {value = configuration.newmetaobject (value) .getValue (propertyName.subString (prop.getName (). length ())) ؛ }} آخر {value = metaObject == null؟ null: metaObject.getValue (propertyName) ؛ } suppressWarnings ("RawTypes") typeHandler typeHandler = parameTerMapping.getTypeHandler () ؛ if (typeHandler == NULL) {رمي executorexception جديد ("لم يتم العثور على typehandler للمعلمة" + propertyName + "من العبارة" + medstatement.getId ()) ؛ } typeHandler.setParameter (ps ، i + 1 ، value ، parameTerMapping.getjdbctype ()) ؛ }}}} / *** QUERY TOTAL RECORDS* PARAM SQL SQL عبارة* param اتصال قاعدة بيانات الاتصال* param mediStatement معرض* @param parameter* @param bOUNDSQL BOUNDSQL MedpedStatement ، معلمة الكائن النهائي ، BODEDSQL BODEDSQL ، سجل السجل) يلقي sqlexception {string dbname = global.getConfig ("jdbc.type") ؛ السلسلة النهائية countsql ؛ if ("oracle" .equals (dbname)) {countsql = "select count (1) from (" + sql + ") tmp_count" ؛ } else {countsql = "select count (1) from (" + removeorders (sql) + ") tmp_count" ؛ } connection conn = connection ؛ أعدت PS = NULL ؛ resultset rs = null ؛ جرب {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) ؛ countbs boundsql = new BONDSQL (MEPTSTATEMTEMNET.GetConfiguration () ، countsql ، boundsql.getParameterMappings () ، parameterObject) ؛ . الانعكاسات. } // Solve mybatis pagination foreach failure end sqlhelper.setparameters (ps ، mappedStatement ، countbs ، parameterObject) ؛ rs = ps.executequery () ؛ عدد int = 0 ؛ if (rs.next ()) {count = rs.getInt (1) ؛ } عدد العائد ؛ } أخيرًا {if (rs! = null) {rs.close () ؛ } if (ps! = null) {ps.Close () ؛ } if (conn! = null) {conn.close () ؛ }}} / *** قم بإنشاء صفحات محددة وفقًا لهجال قاعدة البيانات* param sql sql عبارة في param sql mapper* page paging paging paging* param dialect type* @return paging sql* / public static internatepagesql (string sql ، page <object> elect) Dialect.getLimitString (SQL ، page.getFirStresult () ، page.getMaxResults ()) ؛ } آخر {return sql ؛ }} /*** قم بإزالة جملة تحديد QLString. * param hql * return */ suppressWarnings ("غير مستخدمة") سلسلة ثابتة خاصة removeselect (سلسلة qlstring) {int beginpos = qlstring.toLowerCase (). indexof ("من") ؛ إرجاع QlString.SubString (BeginPos) ؛ } /*** قم بإزالة شرط Orderby من HQL. *param hql *regurn */string static private removeOrders (سلسلة qlstring) {pattern p = pattern.compile ("order // s *by [// w | // w | // s | // s] *" ، pattern.case_insenceitive) ؛ matcher m = p.matcher (qlstring) ؛ StringBuffer SB = New StringBuffer () ؛ بينما (m.find ()) {m.appendReplacement (sb ، "") ؛ } M.Appendtail (SB) ؛ إرجاع sb.tostring () ؛ }}لهجة java واجهة
package com.store.base.secondmodel.base.dialect ؛ / *** على غرار Hibernate ، ولكن فقط جزء الترحيل مبسط* Author yiyong_wu** لهجة الواجهة العامة {/ *** هل تدعم قاعدة البيانات نفسها طريقة الاستعلام الحالية للترحيل للصفحة* الدعم الحالي للاستفادة (لا تدعمها قاعدة البيانات (). / ** * تحويل SQL إلى ترقيم SQL واستدعاء PARAGE SQL بشكل منفصل * * param SQL SQL بيان * param إزاحة عدد البدايات * param حد عدد السجلات التي يتم عرضها لكل صفحة * return sql للاطلاع على query query */ سلسلة getLimitstring العامة (سلسلة sql ، int strem ، int) ؛ }mysqldialect.java
package com.store.base.secondmodel.base.dialect ؛ / ** * تنفيذ لهجة mysql * Author yiyong_wu * */ public class mysqldialect تنفذ لهجة {override public boolean supportlimit () {return true ؛ } Override public string getLimItString (سلسلة SQL ، int intsset ، int limit) {return getLimitSstring (sql ، offset ، integer.toString (Offset) ، integer.toString (limit)) ؛ } /*** قم بتحويل SQL إلى بيان SQL مصبوب ، مما يوفر استبدال الإزاحة والحدود مع العنصر النائب. * <pre> * على سبيل المثال ، mysql * dialect.getLimitString ("SELECT * من المستخدم" ، 12 ، ": إزاحة" ، 0 ، ": LIMIT العامل المركز @REGINTER SQL يحتوي على العناصر النائبة */ السلسلة العامة getLimItString (سلسلة SQL ، int ، إزاحة السلسلة ، السلسلة ، حدود السلسلة) {StringBuilder StringBuilder = new StringBuilder (SQL) ؛ StringBuilder.Append ("limit") ؛ if (Offset> 0) {StringBuilder.Append (OffSetPlaceHolder) .Append ("،"). oppend (limitplaceholder) ؛ } آخر {StringBuilder.Append (limitplaceholder) ؛ } return stringBuilder.toString () ؛ }}تقريبًا هنا شاركنا كيفية تنفيذ الصفحة بأكملها ، ولكن لدينا مهام أكثر أهمية. إذا كنا نريد تشغيل الأمر برمته ، فيجب أن يكون لدينا عمل أساسي للقيام به. بعد ذلك ، نقوم بتحليل المجموعة الكاملة من كائنات الصفحة والهندسة المعمارية ثلاثية الطبقات التي تعتمد عليها ، ونستخدم المنتج ككيان للتحليل. بعد الحديث عن بنية كاملة من ثلاث طبقات ، ستكون المكافآت ممتلئة بالتأكيد. دعنا نتحدث عن ذلك بترتيب الكيان-> Dao-> الخدمة بدوره.
أولاً ، يجب أن نرث فئتين من الكيانات المجردة الأساسية والبيانات لكياناتنا.
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 class class baseentity <T> تنفذ {private Static Final Long SerialVersionuid = 1L ؛ / ** * حذف العلامة (0: Normal ؛ 1: DELETE ؛ 2: AUDIT ؛) */ public Static Final String del_flag_normal = "0" ؛ السلسلة النهائية الثابتة العامة del_flag_delete = "1" ؛ السلسلة النهائية الثابتة العامة del_flag_audit = "2" ؛ / *** رقم الكيان (معرف فريد)*/ معرف السلسلة المحمي ؛ / *** المستخدم الحالي*/ محمي Sturberuser CurrentUser ؛ / *** كائن ترقيم الصفحات الحالي*/ صفحة محمية <T> ؛ / ** * Custom SQL (معرف SQL ، محتوى SQL) */ خريطة خاصة <String ، String> sqlmap ؛ baseentity () {} public baseentity (string id) {this () ؛ this.id = id ؛ } السلسلة العامة getId () {return id ؛ } public void setId (string id) {this.id = id ؛ } / *** سيتم استدعاء هذا عند إجراء تحديثات إدراج لـ Shiro للحصول على المستخدم الحالي* regurn* / jsonignorexmltransient public orgeruser getCurrentuser () {if (currentUser == null) {// currentUser = userUtils.getuser () ؛ } إرجاع CurrentUser ؛ } public void setCurrentUser (Storuser CurrentUser) {this.currentuser = currentUser ؛ } jsonignorexmltransient صفحة عامة <T> getPage () {if (page == null) {page = new page <> () ؛ } صفحة الإرجاع ؛ } الصفحة العامة <T> setPage (صفحة <T> صفحة) {this.page = page ؛ صفحة العودة ؛ } jsonignorexmltransient خريطة عامة <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 () ؛ /*** سواء كان سجلًا جديدًا (افتراضيًا: خطأ) ، اتصل بـ setIsNewRecord () لتعيين سجل جديد ، واستخدام معرف مخصص. * بعد الإعداد إلى True ، يتم إجبار بيان الإدراج على تنفيذها. لن يتم إنشاء المعرف تلقائيًا ويحتاج إلى تمريره يدويًا. * regurn */ public boolean getIsNewRecord () {return stringUtils.isblank (getId ()) ؛ } / *** كائن متغير عالمي* / jsonignore public 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 ؛ استيراد java.util.date ؛ استيراد 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 agract Class DataEntity <T> يمتد baseentity <t> {private static final long serialversionuid = 1l ؛ أسس محمية CreateBy. // Creator محمية تاريخ تم إنشاؤه ؛ // تاريخ الإنشاء المحمي updateby. // updater date المحمي تاريخ التحديث ؛ // تاريخ تحديث السلسلة المحمية delflag ؛ // delete tag (0: normal ؛ 1: delete ؛ 2: Audit) public dataEntity () {super () ؛ this.delflag = del_flag_normal ؛ } dataEntity (string ide) {super (id) ؛ } / ** * تنفيذ الطريقة قبل الإدراج ، تحتاج إلى الاتصال يدويًا * / Override public void preinsert () {// لا يوجد قيود على المعرف على uuid ، استدعاء setIsNewRecord () لاستخدام معرف مخصص // مستخدم 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 orgeruser getCreateby () {return createBy ؛ } public void setCreateBy (Storuser CreateBy) {this.createBy = createBy ؛ } jsonformat (pattern = "yyyy-mm-dd hh: mm: ss") التاريخ العام getCreatedAte () {return createdate ؛ } public void setCreatedAte (date createdate) {this.createdate = createTate ؛ } // jsonignore public orgeupdateby () {return updateBy ؛ } public void setupDateBy (Storuser UpdateBy) {this.updateby = updateBy ؛ } jsonformat (pattern = "yyyy-mm-dd hh: mm: ss") DITE Public Date GetUpdatedate () {return updatedate ؛ } public void setupdatedate (date updatedate) {this.updatedate = updatedate ؛ } jsonignoreLength (min = 1 ، max = 1) السلسلة العامة getDelfLag () {return delflag ؛ } public void setDelfLag (String delflag) {this.delflag = delflag ؛ }}Product.java فئة المنتج
package com.store.base.secondmodel.pratice.model ؛ استيراد com.store.base.secondmodel.base.dataentity ؛ / ***فئة أساسيات المنتج*11 أكتوبر ، 2016*Yiyong_WU*/ منتج الفئة العامة يمتد DataEntity <Tromprow> {Private Static Final Long SerialVersionuid = 1L ؛ سلسلة ProductName الخاصة ؛ سعر التعويم الخاص ؛ سلسلة خاصة المنتج. السلسلة العامة getProductName () {return ProductName ؛ } public void setProductName (string productName) {this.productName = ProductName ؛ } getPrice GetPrice () {سعر الإرجاع ؛ } public void setPrice (سعر التعويم) {this.price = price ؛ } السلسلة العامة getProductNo () {return productNo ؛ } public void setProductNo (String productNo) {this.productno = productNo ؛ }}ماذا عن ذلك؟ هل ترى علاقة ميراث كيان معقدة للغاية؟ لكن ما هو هناك؟ كلما كان الأمر أكثر تعقيدًا ، كلما كان الأمر أكثر اكتمالا. بعد ذلك ، سوف أنظر إلى الطبقة ، نفس الطبقات الثلاث ، جاهزة للمعمد
على أساس الواجهة المحجوزة
حزمة com.store.base.secondmodel.base ؛ / ** * واجهة DAO TOP-MOST * Author Yiyong_wu * */ الواجهة العامة على أساس {} cruddao.java طبقة واجهة DAO للإضافة والحذف والتعديل والاستعلام [java] عرض النسخ العادية طباعة النسخ؟ عرض شظايا رمز على الكود المستمدة إلى حزمة شظايا الكود الخاصة بي com.store.base.secondmodel.base ؛ استيراد java.util.list ؛ / ** * حدد واجهة DAO للإضافة ، والحذف ، والتعديل والاستعلام * Author yiyong_wu * * param <t> */ الواجهة العامة cruddao <t> يمتد على أساس {/ ** * الحصول على قطعة واحدة من البيانات * param id */ truurn */ public t get (معرف السلسلة) ؛ / ** * احصل على جزء واحد من البيانات * @Param Entity * return */ public t get (t untity) ؛ /*** الاستعلام عن قائمة البيانات. إذا كنت بحاجة إلى ترحيل ، فيرجى تعيين كائن الترحيل ، مثل: entity.setPage (صفحة جديدة <T> ()) ؛ * @Param Entity * return */ public list <T> findList (t intity) ؛ / ** * Query جميع قائمة البيانات * @Param Entity * Return */ List Public <T> FindAlllist (T intity) ؛ /*** Query جميع قائمة البيانات* Seee Public List <T> findalllist (t intity)* @REGRURN Public List <T> FindAlllist () ؛ *// ** * إدراج البيانات * @Param Entity * @RETURN */ public int insert (t unity) ؛ / ** * تحديث البيانات * @Param Entity * return */ public int update (t untity) ؛ / ** * حذف البيانات (عادةً ما يكون الحذف المنطقي ، قم بتحديث حقل del_flag إلى 1) * param id * seee public delete (t intity) * regurn */ public int delete (string id) ؛ / ** * حذف البيانات (عادةً ما يكون الحذف المنطقي ، قم بتحديث حقل del_flag إلى 1) * @Param Entity * regurn */ public int delete (t intity) ؛ }ProductDao.java mybatis واجهة المقابلة Mapper هو أيضًا تطبيق DAO. تحتاج إلى تخصيص التعليق التوضيحي @mybatisrepository
package 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 *11 أكتوبر ، 2016 *Yiyong_wu */ @mybatisrepository الواجهة العامة productdao يمتد cruddao <product> {}التعليقات التوضيحية المخصصة MyBatisRepository.java مرتبطة بالتعليقات المخصصة. لن أشرح الكثير هنا ، هناك الكثير من المعلومات عبر الإنترنت.
حزمة com.store.base.secondmodel.base ؛ استيراد java.lang.annotation.documented ؛ استيراد java.lang.annotation.Reentering ؛ استيراد java.lang.annotation.target ؛ استيراد java.lang.annotation.RetentionPolicy ؛ استيراد java.lang.annotation.elementType ؛ استيراد org.springframework.stereotype.component ؛ /*** حدد dao من mybatis لتسهيل مسح {link org.mybatis.spring.mapper.mapperscannerconfigurer}. * *يرجى ملاحظة أنك تريد تكوين التكوين لمسح الفئة المشروحة في ملف تكوين الربيع * *<bean id = "mapperscannerconfigurer"> *<property name = "sqlsessionfactorybeanname" value = "sqlsessionfactory" /> *<property name = "basepackage" name = "enoTationClass" value = "com.store.base.secondmodel.base.mybatisrepository"/> * </bean> "" ؛ } ملاحظة: ملف ProductMapper.xml يحتوي على اتصال قوي مع ProductDao.java هو ملف ProductMapper.xml. يمكنك أن ترى أن مساحة اسم ملف التكوين أعلاه تشير إلى المسار إلى هذا DAO.
بعد ذلك ، ندخل تحليل الخدمة النهائية ، وهو أيضًا ميراث من ثلاث طبقات.
Baseservice.java
حزمة com.store.base.secondmodel.base ؛ استيراد org.slf4j.logger ؛ استيراد org.slf4j.loggerfactory ؛ استيراد org.slf4j.loggerfactory ؛ استيراد org.springframework.transaction.annotation.transactional ؛ / ** * فئة الوالدين من المستوى الأعلى للخدمة * Author yiyong_wu * */ @transactional (readOnly = true) public publics paseservice {// logger logger = loggerfactory.getLogger (getClass ()) ؛ }crudservice.java تنفيذ واجهة الأعمال ذات الصلة
حزمة com.store.base.secondmodel.base ؛ استيراد java.util.list ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.transaction.annotation.transactional ؛ / ** * إضافة وحذف وتعديل والتحقق من فئة قاعدة الخدمة * Author yiyong_wu * * param <d> * param <T> */ public class class crudservice <d يمتد cruddao <t> ، t يمتد البيانات <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; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; استيراد javax.servlet.http.httpservletrequest ؛ استيراد 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; استيراد 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; استيراد java.io.file ؛ استيراد java.io.ioException ؛ استيراد 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); } إرجاع فارغ ؛ } /** * 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; استيراد javax.servlet.http.httpservletrequest ؛ استيراد 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; استيراد 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 باطل؛ } 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(); } /** * Convert to JS to get the object value and generate the three-item operation to return the result* @param objectString object string* For example: row.user.id * Return: !row?'':!row.user?'':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; استيراد javax.servlet.http.httpservletrequest ؛ استيراد javax.servlet.http.httpservletresponse ؛ import org.springframework.beans.factory.annotation.Autowired; استيراد 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 *October 11, 2016*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样式啥的,最后祝福你可以快速掌握这个分页功能!
The above is the skills of the commonly used paging plug-in for Mybatis to implement quick paging. آمل أن يكون ذلك مفيدًا للجميع. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر على الجميع في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!