Прежде чем поделиться кодом выполнения для всей страницы запроса, сначала поймите процесс выполнения.
1. Как правило, он использует Mybatis Plug-In Interceptor для перехвата перед выполнением SQL и добавляйте лимит xx к оператору запроса
2. Используйте объект страницы, чтобы выполнить весь процесс выполнения. Этот объект страницы требует написания фронтальных компонентов страниц в Java.
3. Используйте относительно полный набор трехслойных объектов, DAO и обслуживания для поддержки этой архитектуры страниц
4. Некоторые вспомогательные классы, используемые на этой странице
ПРИМЕЧАНИЕ: есть много общего контента. Я не буду перечислять требуемые банки один за другим. Когда вы используете эту функцию страниц, просто ищите пакеты JAR ночью. Используйте пакет Maven, чтобы импортировать как можно больше, потому что Maven может уменьшить конфликты версий и другие преимущества.
Я могу только сказать, что вы можете использовать эту более простую функцию подкидки как можно быстрее. Если вы этого не понимаете, добавьте меня в QQ и обсудите его вместе. Не ругайся! Кроме того, статья может быть относительно большой, но займет некоторое время, читая ее и практикуя ее определенно получит много.
Шаг 1: Поскольку тема вращается вокруг того, как получить страницу, давайте начнем с Mybatis. Во -первых, мы возьмем еще два важных файла конфигурации, связанные с Mybatis для краткого понимания. Одним из них является mybatis-config.xml, а другой-файл конфигурации Mapper, соответствующий объекту. Я напишу комментарии в файле конфигурации, и все поймут его с первого взгляда.
mybatis-config.xml
<! Конфигурация Doctype public "-// mybatis.org//dtd config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <Конфигурация> <!-Глобальные параметры-> <stults> <!-Сделать глобальную энтузиочную Mapper или Disable Cache. -> <Настройка name = "cacheenabled" value = "false"/> <!-включить или отключить ленивую загрузку глобально. При отключении все связанные объекты загружаются мгновенно. -> <Настройка name = "LazyLoadEnabled" value = "true"/> <!-Когда включено, объект с ленивым свойством загрузки полностью загружает любое свойство при ее вызове. В противном случае каждое свойство будет загружено по мере необходимости. -> <Настройка name = "AggrevessIvelazyLoading" value = "true"/> <!-Допустить ли один SQL возвращать несколько наборов данных (в зависимости от совместимости драйвера) по умолчанию: true-> <Настройка name = "MultiplerSelsEdsEntabled" value = "true"/> <! name = "usecolumnlabel" value = "true"/> <!- разрешить JDBC генерировать первичные ключи. Требуется поддержка привода. Если установить True, этот настройка заставит сгенерированный первичный ключ, некоторые диски несовместимы, но все еще могут быть выполнены. по умолчанию: false-> <Настройка name = "useGeneratedKeys" value = "false"/> <!-Укажите, как MyBatis автоматически отображает столбцы базовых таблиц данных. Нет: не скрывать частичное: часть полная: все-> <Настройка = "AutompanyBehavior" value = "Частичный"/> <! операторы и обновления пакетов)-> <Настройка name = "defaultexeCutortype" value = "simple"/> <!-преобразовать поля с использованием номенклатуры верблюда. -> <настройка name = "mapunderscoretocamelcase" value = "true"/> <!-Установка локального сеанса диапазона кэша: Там будет оператор обмена данными: Введите при вставке нулевого значения-> <настройка name = "jdbctypefornull" value = "null"/> <настройка name = "logprefix" value = "dao."/> </settings> <!-псевдоним-это название более короткого типа java-> <typealias> <typealias type = "com.base.base.model.storeromeRemporeRerOreRemorSomeRemorSomeReReReRemOr Alias = "user"> </typealias> <typealias type = "com.store.base.secondmodel.pratice.model.product" Alias = "Product"> </typealias> <typealias type = "com.store.base.secondmodel.base.page" alias = "page"> </typeal.s.model. ПЕРЕДЕЛЕЖДЕНИЕ ПЕРЕДЕЛЕЙСКОЙ ПЕРЕДЕЛАНИЯ для Mybatis, и нам нужно реализовать эту страницу -перехватчика сами -> <blicins> <plugin receptor = "com.store.base.secondmodel.base.pageinterceptor.paginationInterceptor"/> </placins> </configuration>>
Productmapper.xml используется в качестве тестового объекта, и этот файл Mapper просто настраивает оператор запроса, который необходимо использовать.
<? 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"> <mapper.org/dtd/mybatis-3-mapper.dtd " namespace = "com.store.base.secondmodel.pratice.dao.productdao"> <sql id = "basecolumns"> id, product_name как productnam resultType = "com.store.base.secondmodel.pratice.model.product"> select <include refid = "basecolumns"/> from t_store_product </selet> </mapper>
Шаг 2: Далее мы проведем углубленный анализ и обучение для этого перехватчика страниц, в основном включая следующие классы и их соответствующие интерфейсы
(1) Baseinterceptor Interceptor Basic Class
(2) PaginationInterceptor Класс плагинов страниц, который мы хотим использовать, наследуйте вышеуказанный базовый класс
(3) SQLHELPER в основном используется для заранее выполнения операторов подсчета, а также для получения всего полного оператора страниц.
(4) Диалект, mysqlidialect, в основном используется для того, поддерживает ли база данных ограниченные операторы, а затем инкапсулирует полные ограниченные операторы
Ниже приведены дисплеи обмена этими категориями
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; import com.store.base.secondmodel.base.global; import com.store.base.secondmodel.base.page; import com.store.base.secondmodel.base.dialect.dialect; import com.store.base.secondmodel.base.dialect.mysqlidialect; Import com.store.base.util.reflections; / ** * Mybatis Pagination Interceptor Base Class * @author yiyong_wu * */ public Abstract Class Baseinterceptor реализует Interceptor, Serializable {Private Static Long Long Serialversionuid = 1L; Защищенная статическая конечная строка PAGE = "PAGE"; Защищенная статическая конечная строка Delegate = "делегат"; Защищенная статическая конечная строка maped_statement = "MapedStatement"; Защищенный log log = logfactory.getLog (this.getClass ()); защищенный диалект диалекта; / *** Преобразовать и проверить параметры* @param parameterObject parameterObject parameterObject* @param page page object* @return pagination объект* @throws nosuchfieldexception Параметр не может быть найден*/ @suppresswarnings («uncecked») Protatic Static <object> ConvertPariste (ParameterObject («объект> parameterObrie {return (page <Object>) parameterObject; } else {return (page <Object>) Reflections.getFieldValue (parameterObject, page); }} catch (Exception e) {return null; }} /*** Установите свойства, поддержка пользовательских классов диалектов и как сформулировать базы данных* <code> Dialectclass < /code>, пользовательские классы диалекта. Это может быть настроено без настройки * <ODE> DBMS </ODE> Тип базы данных, базу данных, поддерживаемой подключаемой * <code> SQLPattern </code> SQL ID, который необходимо перехватить * @param P Properties */Protected void initProperties (свойства P) {dialect = null; String dbtype = global.getConfig ("jdbc.type"); if ("mysql" .equals (dbtype)) {dialect = new mysqlidialect (); } if (dalect == null) {бросить новое runtimeexception ("ошибка диалекта mybatis."); } Dialect = dialect; }}PaginationInterceptor.java
пакет 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; import com.store.base.secondmodel.base.page; import com.store.base.secondmodel.base.util.stringutils; Import com.store.base.util.reflections; /*** Плагин подкидки базы данных, только перехватывает операторы запроса. * @author yiyong_wu * */ @Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class PaginationInterceptor extends BaseInterceptor { private static final long serialVersionUID = 1L; @Override Public Object Intercept (vocation vocation) Throws Throwable {final MapedStatement MapedStatement = (MapedStatement) vlocation.getArgs () [0]; Объект параметр = vocation.getargs () [1]; BoundsQl BoundsQl = mapedStatement.getBoundSql (параметр); Объект parameterObject = boundsql.getParameterObject (); // Получить страницу объекта параметра лиц <object> page = null; if (parameterObject! = null) {page = convertParameter (parameterObject, page); } // Если объект пейджинга установлен, пейджинг выполняется if (page! = Null && page.getPagesize ()! = -1) {if (stringUtils.isblank (boundsql.getsql ()))) {return null; } String OriginalSql = boundsql.getSql (). Trim (); // Получить общее количество записей page.setCount (sqlHelper.getCount (OriginalSQL, NULL, отображение Statatement, ParameterObject, BoundsQl, log)); // Запрос на страницы локализованные объекты для изменения базы данных и обратите внимание на изменение строки реализации pagesql = sqlhelper.generatepagesql (OriginalSQL, Page, Dialect); vocation.getArgs () [2] = new Rowbounds (rowbounds.no_row_offset, rowbounds.no_row_limit); Boundsql newboundsql = new Boundsql (mapedStatement.getConfiguration (), pagesql, boundsql.getParametermAppings (), boundsql.getParameterObject ()); // Решение mybatis pagination for pareach affect parameter wart of if (Reflections.getfieldvalue (boundsql, "metaparameters")! = Null) {metaobject mo = (metaobject) Reflections.getFieldValue (Boundsql, "MetAparameters"); Reflections.SetFieldValue (NewBoundSQL, "Metaparameters", MO); } // Решение Mybatis Pagination For Pareach Ошибка сбоя конец MapedStatement newms = copyFrommapedStatement (MapedStatement, New BoundsqlsqlSource (newboundSQL)); vocation.getArgs () [0] = newms; } return villocation.proceed (); } @Override public Object Plugin (объект Target) {return plugin.wrap (target, this); } @Override public void setProperties (свойства свойств) {super.initProperties (свойства); } private MapedStatement CopyFrommAppStatement (MapedStatement MS, SQLSource NewsqlSource) {MapedStatement.Builder Builder = new MapedStatement.Builder (Ms.getConfiguration (), Ms.getid (), NewsqlSource, Ms.getsqlomamandtype ();); 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 boundsqlsqlsource реализует sqlsource {boundsql boundsql; public boundsqlsqlsource (boundsql boundsql) {this.boundsql = boundsql; } @Override public boundsql getBoundsql (объект 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; Импорт 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; import com.store.base.secondmodel.base.global; import com.store.base.secondmodel.base.page; import com.store.base.secondmodel.base.dialect.dialect; import com.store.base.secondmodel.base.util.stringutils; Import com.store.base.util.reflections; /*** Класс инструмента SQL* @author yiyong_wu** /public class sqlhelper { /*** По умолчанию частный конструктор* /private sqlhelper () {} /*** Установите значение для параметров sql (?), См. SQL объект утверждения. * @param MapedStatement MapedStatement * @param boundsql sql * @param parameterobject parameterobject parameterobject @throws java.sql.sqlexception Исключение базы данных */ @SuppressWarning ParameterObject) Throws SQLexception {errorContext.Instance (). Activity («Параметры настройки»). Object (mapedStatement.getParameterMap (). getId ()); Список <parametermapping> parametermAppings = boundsql.getParameterMappings (); if (parametermappings! = null) {configuration configuration = mapedStatement.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) {значение объекта; 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) && boundsql.hasadditionalParameter (prop.getName ())) {value = boundsql.getAdditionalParameter (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 = parametermapp.gettypehandler (); if (typehandler == null) {бросить новое executorexception («Не было найдено typehandler для параметра» + PropertyName + »утверждения» + mapedStatement.getId ()); } typeHandler.setParameter (ps, i + 1, значение, параметрирование. GetJdbctype ()); } } } } /** * Query total records* @param sql SQL statement* @param connection Database connection* @param mappedStatement mapped * @param parameterObject parameter* @param boundSql boundSql * @return Total number of records* @throws SQLException sql query error*/ public static int getCount(final String sql, final Connection connection, final MappedStatement MapedStatement, Final ParameterObject, Final BoundsQl BoundsQL, log) Throws SQLexception {string dbName = global.getConfig ("jdbc.type"); окончательная строка ountsql; if ("oracle" .equals (dbname)) {countsql = "select count (1) из (" + sql + ") tmp_count"; } else {countsql = "select count (1) из (" + removeorders (sql) + ") tmp_count"; } Соединение connect = connection; Подготовленное предприятие 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 = mapedStatement.getConfiguration (). getEnvironment (). getDataSource (). getConnection (); } ps = conn.prepareStatement (countsql); Boundsql Countbs = new BoundsQl (mapedStatement.getConfiguration (), gountsql, boundsql.getParameterMappings (), parameterObject); // Решение mybatis pagination for pareach affect parameter wart of if (Reflections.getfieldvalue (boundsql, "metaparameters")! = Null) {metaobject mo = (metaobject) Reflections.getFieldValue (Boundsql, "MetAparameters"); Reflections.setfieldvalue (Countbs, "Metaparameters", Mo); } // Решение mybatis pagination for for Paramefore enform end sqlhelper.setParameters (PS, MapedStatement, 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 SQL dialect.getLimitstring (sql, page.getfirstresult (), page.getmaxResults ()); } else {return sql; }} /*** Удалите предложение SELECT QlString. * @param hql * @return */ @suppresswarnings ("неиспользованный") частная статическая строка removeselect (string qlstring) {int beginpos = qlString.tolaycome (). indexof ("from"); return qlstring.substring (beginpos); } /*** Удалите пункт Orderby HQL. *@param hql *@return */private static String removeorders (string qlString) {pattern p = pattern.compile ("order // s *by [// w | // w | // s | // s] *", pattern.case_insensitiot); Matchter M = P.Matcher (QlString); StringBuffer sb = new StringBuffer (); while (m.find ()) {m.appendReplacement (sb, ""); } m.ppendtail (sb); вернуть sb.toString (); }}Dialect.java Interface
пакет com.store.base.secondmodel.base.dialect; / *** Аналогично hibernate, но только часть пейджинга упрощена* @author yiyong_wu**/ public interface Dialect {/ *** Поддерживает ли сама база данных текущий метод подкрепления для пейджин* Если база данных не поддерживает ее, база данных не будет Paging* @return True: поддерживает Quage Quere. / ** * Преобразовать SQL в Pagination SQL и подключение к вызову SQL отдельно * * @param SQL SQL оператор * @param Смещение. Номер запуска * @param ограничивается, сколько записей отображается на страницу * @return sql для запроса на страницы */ public String getLimitstring (String Sql, Int Offset, Int Limit); }Mysqlidialect.java
пакет com.store.base.secondmodel.base.dialect; / ** * Реализация mysql Dialect * @author yiyong_wu * */ public class mysqlidialect реализует диалект {@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 (Limit)); } /*** Включите SQL в оператор SQL, обеспечивая замену смещения и лимита с заполнителем. * <pre> * For example, mysql * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") will return * select * from user limit :offset,:limit * </pre> * * @param sql Actual SQL statement * @param offsetPlaceholder Pagination start record number * @param offsetPlaceholder Pagination start record number - placeholder Pagination record number Placeholder @return Pagination SQL, содержащий заполнители */ public String getLimitsTring (String SQL, Int Offset, String OffsetPlaceholder, String Limitplaceholder) {StringBuilder StringBuilder = new StringBuilder (SQL); stringBuilder.append ("Limit"); if (offset> 0) {stringBuilder.append (OffsetPlaceholder) .append (","). Append (Limitplaceholder); } else {stringBuilder.Append (LimitplayPhorter); } 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; Import org.apache.commons.lang3.builder.reflectionToStringBuilder; Import com.fasterxml.jackson.annotation.jsonignore; Импорт com.google.common.collect.maps; Import com.store.base.model.storeuser; / ** * Сущность верхнего уровня * @author yiyong_wu * * @param <t> */ public abstract class baseentity <t> реализует serializable {private static final long serialversionuid = 1l; / ** * Удалить тег (0: нормальный; 1: удалить; 2: аудитор;) */ public static final String del_flag_normal = "0"; Общественная статическая конечная строка del_flag_delete = "1"; публичная статическая конечная строка del_flag_audit = "2"; / *** Номер объекта (уникальный идентификатор)*/ Защищенный идентификатор строки; / *** Текущий пользователь*/ защищенный магазин CurrentUser; / *** Текущий объект странификации объекта*/ Защищенная страница <t> Page; / ** * Custom SQL (SQL Identifier, SQL Content) */ Private Map <String, String> SQLMAP; public baseentity () {} public baseentity (String id) {this (); this.id = id; } public String getId () {return id; } public void setId (String id) {this.id = id; } / **! } return currentUser; } public void setCurrentUser (StoreUser CurrentUser) {this.currentuser = currentUser; } @Jsonignore @xmltransient public Page <t> getPage () {if (page == null) {page = new Page <> (); } return Page; } public page <t> setPage (page <t> page) {this.page = page; вернуть страницу; } @Jsonignore @xmltransient public map <string, string> getsqlmap () {if (sqlmap == null) {sqlmap = maps.newhashmap (); } return sqlmap; } public void setSqlMap (map <string, string> sqlmap) {this.sqlmap = sqlmap; } / ** * Выполнить метод перед вставкой, подклассы реализуют * / public Abstract void preansert (); / ** * Выполнить метод перед обновлением, подклассы реализуют */ public Abstract void preupdate (); /*** Будь то новая запись (по умолчанию: false), вызов setisnewRecord (), чтобы установить новую запись и использовать пользовательский идентификатор. * После настройки в True оператор INSERT вынужден быть выполненным. Идентификатор не будет автоматически сгенерирован и должен быть передан вручную. * @return */ public boolean getisnewRecord () {return stringUtils.isblank (getId ()); } / *** Глобальный объект переменной* / @jsonignore public global getglobal () {return global.getinstance (); } / *** Получить имя базы данных* / @jsonignore public String getDbname () {return global.getConfig ("jdbc.type"); } @Override public String toString () {return ReflectionToStringBuilder.toString (this); }}DataStity.java, в основном хранит обновление и удаление времени, создайте пользователя, обновите пользователя, логический флаг удаления и т. Д.
пакет com.store.base.secondmodel.base; импортировать java.util.date; Импорт org.hibernate.validator.constraints.length; Import com.fasterxml.jackson.annotation.jsonformat; Import com.fasterxml.jackson.annotation.jsonignore; Import com.store.base.model.storeuser; / ** * Data Entity * @author yiyong_wu * * @param <t> */ public abstract class dataStity <t> расширяет baseentity <t> {private static final long serialversionuid = 1l; Защищенный магазин Createby; // Создатель защищенный дата создана; // Дата создания защищенного магазина updateby; // Обновленная дата обновления // Обновленная дата защищенная строка Delflag; // удалить тег (0: нормальный; 1: удалить; 2: аудитор) public DataStity () {super (); this.delflag = del_flag_normal; } public DataStity (String Id) {super (id); } / ** * Выполнить метод Перед вставкой, вам необходимо вручную вызову * / @Override public void preinsert () {// Нет ограничения на идентификатор UUID, Call SetIsNewRecord () для использования пользовательского идентификатора // user user = userUtils.getUser (); // if (stringutils.isnotblank (user.getid ())) {// this.updateby = user; // this.createby = user; //} this.updateTate = new Date (); this.createdate = this.updateTate; } / ** * Выполнить метод перед обновлением, вам необходимо вручную вызовать * / @Override public void preupdate () {// user user = userUtils.getuser (); // if (stringutils.isnotblank (user.getid ())) {// this.updateby = user; //} this.updateTate = 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 cantenate; } public void setCreatedAte (дата создан) {this.createdate = censueTate; } // @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 (дата обновления) {this.updateTate = updateTate; } @Jsonignore @length (min = 1, max = 1) public String getDelflag () {return delflag; } public void setDelflag (string delflag) {this.delflag = delflag; }}Product.java Product Category
пакет com.store.base.secondmodel.pratice.model; Import com.store.base.secondmodel.base.dataEntity; / ***Класс Основы продукта*11 октября 2016 г.*yiyong_wu*/ public class product расширяет DataStity <Продукт> {Частный статический конечный длинный сериал -ряд = 1L; Private String ProductName; Частная цена поплавок; частная строка продукта; public String getProductName () {return ProductName; } public void setProductName (String productName) {this.ProductName = productName; } public float getPrice () {return Price; } public void setPrice (float Price) {this.price = price; } public String getProductno () {return productNo; } public void setProductno (String productNo) {this.Productno = productNo; }}Как насчет этого? Вы видите очень сложные отношения наследования сущности? Но что там? Чем сложнее, тем более он будет полным. Далее я посмотрю на слой, те же три слоя, готовые к крещению
Basedao.java зарезервированный интерфейс
пакет com.store.base.secondmodel.base; / ** * Top-Most Interface * @author yiyong_wu * */ public interface basedao {} cruddao.java interface stare для добавления, удаления, модификации и запроса [java] Просмотр печатной печати? Просмотреть фрагменты кода на коде, полученный в пакете моего кода, com.store.base.secondmodel.base; импортировать java.util.list; / ** * Определите интерфейс DAO для добавления, удаления, модификации и запроса * @author yiyong_wu * * @param <t> */ public interface cruddao <t> extends basedao {/ ** * Получить единую часть данных * @param id * @return */ public t get (string id); / ** * Получить один кусок данных * @param entity * @return */ public t get (t entity); /*** Запрос список данных. Если вам нужна пейджинг, установите объект Paging, такой как: Entity.SetPage (новая страница <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) * @param id * @see public int delete (t entity) * @return */ public int delete (String Id); / ** * Удалить данные (обычно логическое удаление, обновите поле del_flag до 1) * @param entity * @return */ public int delete (t entity); }ProductDao.java mybatis соответствующий интерфейс Mapper также является реализацией DAO. Вам нужно настроить аннотацию @mybatisrepository
пакет com.store.base.secondmodel.pratice.dao; import com.store.base.secondmodel.base.cruddao; Import com.store.base.secondmodel.base.mybatisrepository; import com.store.base.secondmodel.pratice.model.product; / ** *todo *11 октября 2016 г. *yiyong_wu */ @mybatisrepository product productdao extends 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; Import org.springframework.stereotype.component; /*** Определите DAO Mybatis, чтобы облегчить сканирование {@link org.mybatis.spring.mapper.mapperscannerConfigurer}. *Обратите внимание, что вы хотите настроить конфигурацию для сканирования аннотированного класса в файле конфигурации пружины * *<bean id = "mapperscannerconfigurer"> *<name = "sqlSessionFactoryBeanName" value = "sqlSessionFactor name = "annotationclass" value = "com.store.base.secondmodel.base.mybatisrepository"/> * </bean> * @author yiyong_wu * */@retention (retentionpolicy.runtime) @target (elementtype.type) @documented @component @Interface mybatface @Interface @Interface @Interface @Interface @Interface @Interface @Interface. по умолчанию ""; } ПРИМЕЧАНИЕ. Файл 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) открытый абстрактный класс baseservice {// Защищенный 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 abstract class crudservice <d extends cruddao <t>, t Extends DataEntity <T>> exters BaseService {/ ** * Persistence Layer Protection Protectured DaUtepection DaUtepection DaUtepection DaUtepection DaUtepection DaUtepection DaUtepection DaUtepection DaUtepection DaUTOWSIRESIED DAO / ** * Получить один кусок данных * @param id * @return */ public t get (string id) {return dao.get (id); } / ** * Получить один кусок данных * @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; импортировать 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); } return 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; Импорт 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; /** * 取得存储在静态变量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { assertContextInjected(); return applicationContext; } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } @Override public void destroy() throws Exception { SpringContextHolder.clearHolder(); } /** * 实现ApplicationContextAware接口, 注入Context到静态变量中. */ @Override public void setApplicationContext(ApplicationContext applicationContext) { logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext); SpringContextHolder.applicationContext = applicationContext; if (SpringContextHolder.applicationContext != null) { logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); } } /** * 清除SpringContextHolder中的ApplicationContext为Null. */ public static void clearHolder() { if (logger.isDebugEnabled()){ logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); } applicationContext = null; } /** * 检查ApplicationContext不为空. */ private static void assertContextInjected() { Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."); } }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; }}} вернуть 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!