Antes de compartilhar o código de execução para toda a página de consulta, entenda o processo de execução primeiro.
1. Geralmente, ele usa o interceptador de plug-in mybatis para interceptar antes da execução do SQL e adicionar limite xx à instrução de consulta
2. Use um objeto de página para executar todo o processo de execução. Este objeto de página requer escrever componentes de paginação front-end em Java.
3. Use um conjunto relativamente completo de entidade de três camadas, DAO e serviço para apoiar esta arquitetura de paginação
4. Algumas classes auxiliares usadas nesta página
Nota: Há muito conteúdo compartilhado. Não vou listar os frascos necessários um por um. Quando você usa essa função de paginação, procure pacotes JAR à noite. Use o pacote Maven para importar o máximo possível, porque o Maven pode reduzir os conflitos de versão e outras vantagens.
Só posso dizer que você pode usar essa função de paginação mais fácil o mais rápido possível. Se você não entende, adicione -me ao QQ e discuta isso juntos. Não jure! Além disso, o artigo pode ser relativamente grande, mas demorando algum tempo, lendo e praticando -o definitivamente ganhará muito.
Etapa 1: como o tópico gira em torno de como pagar, vamos começar com o Mybatis. Primeiro, retiraremos mais dois arquivos de configuração importantes relacionados ao MyBatis para um breve entendimento. Um é o mybatis-config.xml, e o outro é o arquivo de configuração do mapeador correspondente à entidade. Vou escrever comentários sobre o arquivo de configuração e todos o entenderão rapidamente.
mybatis-config.xml
<! Doctype Configuration public "-// mybatis.org//dtd Config 3.0 // pt" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <figurting Parameters ou DISTERS-<!-. -> <Configuração name = "Cacheenabled" value = "false"/> <!-Ativar ou desativar o carregamento preguiçoso globalmente. Quando desativado, todos os objetos associados são carregados instantaneamente. -> <Configuração name = "LazyLoadingEnabled" value = "true"/> <!-Quando ativado, um objeto com uma propriedade de carregamento preguiçoso carregará totalmente qualquer propriedade quando é chamada. Caso contrário, cada propriedade será carregada conforme necessário. -> <Configuração name = "agressiveLAzyLoading" value = "true"/> <!-Se deve permitir que um único SQL retorne vários conjuntos de dados (dependendo da compatibilidade do driver) padrão: true-> <Configuração Nome = "MultiPleResultsetsenabled" Value = "True"/> <!-de Alias para as colunas pode ser usado (dependendo de depende (depende de "/! name = "usecolumnLabel" value = "true"/> <!- Permitir que o JDBC gere chaves primárias. O suporte da unidade é necessário. Se definido como true, essa configuração forçará a chave primária gerada, algumas unidades são incompatíveis, mas ainda podem ser executadas. Padrão: false-> <Configuração name = "useGeneratedKeys" value = "false"/> <!-Especifique como o Mybatis mapeia automaticamente as colunas da tabela de base de dados, nenhuma: não obscurecendo parcial: parte completa: all-> <definição de nome "simples; simples; simples: simples: simples: simples; simples: slots simples: simples: slots simples: simples: stats stats stats: simples: stats sTTSTSOTBEHAVIOR": "parcial"/> <!-isto é o que é o tipo de exceção (simples; pode repetir instruções e atualizações em lote)-> <Configuração name = "defaultExecutyType" value = "simples"/> <!-Converter campos usando a nomenclatura de camelo. -> <Configuração name = "mapundersCoretocameLCase" value = "true"/> <!-Definindo sessão de intervalo de cache local: haverá instrução de compartilhamento de dados: escopo da instrução (não será compartilhamento de dados) Defalut: Session-> <Configurando o nome = "LocalCescope" Value = "Sessão"/! type when inserting a null value --> <setting name="jdbcTypeForNull" value="NULL"/> <setting name="logPrefix" value="dao."/> </settings> <!--Alias is the name of a shorter Java type --> <typeAlias> <typeAlias type="com.store.base.model.StoreUser" alias = "Usuário"> </tytyeAlias> <typeAlias type = "com.store.base.secondmodel.pratice.model.product" alias = "Product"> </typeAlias> <typEalias type = "com.store.base.base.base.base.page" <sias "" Page.Stage.Base.Base.Secondmodel.Base.Page "ALIAS =" Um interceptador de página configurado para mybatis, e precisamos implementar esta página nos interceptor -> <flugins> <plugin interceptor = "com.store.base.secondmodel.base.pageIntercept.paginationInterceptor"/> </plugins> </figuration>
Um ProductMapper.xml é usado como um objeto de teste, e esse arquivo de mapeador simplesmente configura uma declaração de consulta que precisa ser usada.
<? xml versão = "1.0" coding = "utf-8"?> <! namespace = "com.store.base.secondmodel.pratice.dao.productdao"> <sql id = "basecolumns"> id, product_name como productName, product_no como produto, preço como preço </sql> <select id = "findList" ResultType = "com.store.base.secondmodel.pratice.model.product"> selecione <incluir refid = "basecolumns"/> de t_store_product </leclect> </spurper>
Etapa 2: Em seguida, realizaremos análises e aprendizagem detalhados para este interceptador de paginação, incluindo principalmente as aulas a seguir e suas interfaces correspondentes
(1) classe BASEINTECTORDOR CLASSE BASIC
(2) Paginação -interceptor A classe de plug -in de paginação que queremos usar, herde a classe básica acima
(3) Sqlhelper é usado principalmente para executar declarações de contagem com antecedência e também para obter toda a declaração completa da paginação.
(4) O dialeto, MySqldialect, é usado principalmente para se o banco de dados suporta instruções limitadas e depois encapsula as instruções limitadas completas
A seguir, são apresentados os monitores de compartilhamento dessas categorias
BaseIntercept.java
pacote com.store.base.secondmodel.base.pageInterceptor; importar java.io.serializable; importar java.util.properties; importar org.apache.ibatis.logging.log; importar org.apache.ibatis.logging.logFactory; importar org.apache.ibatis.plugin.intercept; importar com.store.base.secondmodel.base.global; importar com.store.base.secondmodel.base.page; importar com.store.base.secondmodel.base.dialect.dialect; import com.store.base.secondmodel.base.dialect.mysqldialect; importar com.store.base.util.reflections; / ** * Mybatis Paginação Interceptor Classe * @author yiyong_wu * */ public Resumo Classe BaseIntercept Iplementos interceptores, serializável {private estático final serialversionuid = 1L; Página de sequência final estática protegida = "Page"; String estática final protegida delegate = "Delegate"; String final estática protegida maped_statement = "mapedstatement"; log protegido log = logFactory.getLog (this.getClass ()); dialeto de dialeto protegido; / *** Converte e verifique os parâmetros* @param parameterObject ParameterObject ParameTerObject* @param Página Objeto de paginação* @return Objeto de paginação* @Throws O parâmetro NosuchfieldException não pode ser encontrado*/ @SUPletSwarnings ("UNLHECKED") Página estática protegida <Bejet> (ObjectWarnings,) (Página <ject>) parameterObject; } else {return (página <bject>) reflection.getfieldValue (parameterObject, página); }} catch (Exceção e) {return null; }} /*** Defina propriedades, suporta classes de dialeto personalizadas e como formular bancos de dados* <code> dialectclass </code>, classes de dialeto personalizadas. Isso pode ser configurado sem configurar * <ede> dbms </ode> Tipo de banco de dados, banco de dados suportado pelo plug-in * <code> sqlpattern </code> sql ID que precisa ser interceptado * @param String dbtype = global.getConfig ("jdbc.type"); if ("mysql" .equals (dbtype)) {dialect = new mySqlDialect (); } if (dalect == NULL) {lança nova RunTimeException ("Erro de dialeto mybatis."); } Dialeto = dialeto; }}PaginaçãoIntercept.java
pacote com.store.base.secondmodel.base.pageInterceptor; importar java.util.properties; importar org.apache.ibatis.executor.executor; importar org.apache.ibatis.mapping.boundsql; importar org.apache.ibatis.mapping.Mappedstatement; importar org.apache.ibatis.mapping.sqlsource; importar org.apache.ibatis.plugin.intercepts; importar org.apache.ibatis.plugin.invocation; importar org.apache.ibatis.plugin; importar org.apache.ibatis.plugin.signature; importar org.apache.ibatis.reflection.metaObject; importar org.apache.ibatis.session.ResultHandler; importar org.apache.ibatis.session.rowbounds; importar com.store.base.secondmodel.base.page; importar com.store.base.secondmodel.base.util.stringutils; importar com.store.base.util.reflections; /*** Plug -in de paginação de banco de dados, intercepta apenas as instruções de consulta. * @author yiyong_wu * */ @intercepts ({@signature (type = executor.class, method = "Query", args = {mapedstatement.class, object.class, liquidsiSiSiScentSinterInterSInterSInterSInterSInterSoRSINTERS, RESUTHANDLER.Class})) PAGINA PAGINAINTENTENDORS.CLASS. @Override Public Object Intercept (Invocation Invocation) lança arremesso {Final MappEdStatement MappEdStatement = (MappEdStatement) Invocation.getargs () [0]; Parâmetro do objeto = Invocation.getargs () [1]; Boundsql Boundsql = MappEdStatement.GetBoundSql (parâmetro); Objeto parameterObject = boundSql.getParameToBject (); // Obtenha a página do objeto do parâmetro de paginação <BECT> página = null; if (parameterObject! = null) {página = convertParameter (parameterObject, página); } // Se o objeto de paginação estiver definido, a paginação será executada se (página! = Null && page.getPagesize ()! } String Originalsql = Boundsql.getSql (). TRIM (); // Obtenha o número total de registros Page.SetCount (SQLHelper.GetCount (OriginalSQL, NULL, MappedStatement, ParameterObject, Boundsql, log)); // Paginação Consulta Objetos localizados para modificar o banco de dados e prestar atenção à modificação da String de implementação PAGESQL = SQLHelper.GeneratePagesql (Originalsql, Page, Dialect); Invocation.getargs () [2] = new RowBounds (rowbounds.no_row_offset, rowbounds.no_row_limit); Boundsql newboundSql = new Boundsql (MappEdStatement.GetConfiguration (), Pagesql, Boundsql.getParameterMappings (), Boundsql.getParameterObject ()); // Resolva a falha do parâmetro da paginação mybatis para a falha do parâmetro if (reflexões.getfieldValue (boundsql, "metaparameters")! = Null) {metaObject mo = (metaobject) reflexões.getfieldValue (boundsql, "metaparameters"); Reflexões.SetFieldValue (Newboundsql, "Metaparameters", MO); } // Resolva a paginação mybatis para a falha do parâmetro FAIDA MAPPEDSTATEMENT newms = copyFroMpoupstatement (MappedStatement, new BoundsqlSqlSource (newboundSql)); invocação.getargs () [0] = newms; } retornar invocação.proeced (); } @Override public Object Plugin (destino do objeto) {return plugin.wrap (Target, este); } @Override public void setProperties (Propriedades Propriedades) {super.initProperties (Propriedades); } MAPPEDSTATEMENT PRIVADO COPYFROMAPTATEMENT (MAPPEDSTATEMENT MS, SQLSource NewsQLSource) {MappedStatement.Builder Builder = new MappEdStatement.builder (ms.getConfiguration (), ms.getId (), Newsqlsource, ms.getClommp (), ms.getconfiguration (), ms.getId (), Newsqlsource, ms.getClomrty; construtor.Resource (ms.getResource ()); builder.FetchSize (ms.getFetchSize ()); builder.statementType (ms.getStatementType ()); construtor.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 ()); construtor.cache (ms.getcache ()); retorno construtor.build (); } classe estática pública BoundsqlSqlSource implementa SQLSource {Boundsql Boundsql; public BoundsqlSqlSource (Boundsql Boundsql) {this.BoundSql = Boundsql; } @Override public boundsql getBoundSql (objeto parameterObject) {return boundsql; }}}Sqlhelper.java
pacote com.store.base.secondmodel.base.pageInterceptor; importar java.sql.connection; importar java.SQL.PreparedStatement; importar java.sql.resultset; importar java.sql.sqLexception; importar java.util.list; importar java.util.regex.matcher; importar java.util.regex.pattern; importar org.apache.ibatis.executor.errorContext; importar org.apache.ibatis.executor.executorexception; importar org.apache.ibatis.logging.log; importar org.apache.ibatis.mapping.boundsql; importar org.apache.ibatis.mapping.Mappedstatement; importar org.apache.ibatis.mapping.parameterMapping; importar org.apache.ibatis.mapping.parametermode; importar org.apache.ibatis.reflection.metaObject; importar org.apache.ibatis.reflection.property.propertyTokenizer; importar org.apache.ibatis.scripting.xmltags.foreachsqlnode; importar org.apache.ibatis.session.configuration; importar org.apache.ibatis.type.typehandler; importar org.apache.ibatis.type.typeHandlerRegistry; importar com.store.base.secondmodel.base.global; importar com.store.base.secondmodel.base.page; importar com.store.base.secondmodel.base.dialect.dialect; importar com.store.base.secondmodel.base.util.stringutils; importar com.store.base.util.reflections; /*** classe de ferramenta sql* @author yiyong_wu** /public class sqlhelper { /*** Construtor privado padrão* /private sqlhelper () {} /*** defina o valor para parâmetros sql (?), Refere -se a org.aPeeter.ibatis *exor.par.parter.pareMeter.PeReFR.PeReFR.Estr. SQL o objeto da declaração. * @param mappedStatement MappedStatement * @param boundSql SQL * @param parameterObject ParameterObject ParameterObject @throws java.sql.SQLException Database exception*/ @SuppressWarnings("unchecked") public static void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Objeto parameterObject) lança sqLexception {ErrorContext.Instance (). Activity ("Configurando parâmetros"). Object (mapedstatement.getParameterMap (). GetId ()); Lista <MeameTerMapping> parameTerMAppings = boundSql.getParameterMAppings (); if (parameTerMAppings! = null) {configuração 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) {value objeto; 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 (valor! }} else {value = metaObject == null? null: metaobject.getValue (PropertyName); } @Suppresswarnings ("RawTypes") typeHandler typeHandler = parameTerMapping.getTypeHandler (); if (typeHandler == null) {tiro novo executoraException ("Não houve TypeHandler encontrado para o parâmetro" + PropertyName + "OF Declaration" + MappEdStatement.getId ()); } typeHandler.setParameter (ps, i + 1, valor, parametermapping.getjdbctype ()); }}}} /** MAPPEDSTATEMENT MAPPEDSTATEMENT, FINAL PARAMETEROBJETO DE PARTEM, LIGHTSQL LIGHTSQL, LOG LOG) lança SQLEXCECCIONE {String dbName = global.getConfig ("jdbc.type"); Final String CountSQL; if ("oracle" .equals (dbname)) {countSql = "Selecione contagem (1) de (" + sql + ") tmp_count"; } else {countSql = "Selecione count (1) de (" + removeders (sql) + ") tmp_count"; } Conexão conn = conexão; Preparado estatement ps = null; ResultSet rs = null; tente {if (log.isdebugenabled ()) {log.debug ("count sql:" + stringUtils.replaceEach (contagemql, new string [] {"/n", "/t"}, new string [] {"" ""}); } if (conn == null) {conn = mapedstatement.getConfiguration (). getenvironment (). getDataSource (). getConnection (); } ps = Conn.Preparestatement (contagemSQL); Boundsql countbs = new Boundsql (MappEdStatement.getConfiguration (), countSQL, boundsql.getParameterMAppings (), parameterObject); // Resolva a falha do parâmetro da paginação mybatis para a falha do parâmetro if (reflexões.getfieldValue (boundsql, "metaparameters")! = Null) {metaObject mo = (metaobject) reflexões.getfieldValue (boundsql, "metaparameters"); Reflexões.SetFieldValue (Countbs, "Metaparameters", MO); } // Resolva a paginação mybatis para a falha do parâmetro END SQLHelper.setParameters (PS, MappEdStatement, Countbs, ParameTerObject); rs = ps.executeQuery (); int conting = 0; if (rs.Next ()) {count = rs.getInt (1); } contagem de retorno; } finalmente {if (rs! = null) {rs.close (); } if (ps! = null) {ps.close (); } if (conn! = null) {Conn.Close (); }}} / *** Gere páginas específicas de acordo com o dialeto do banco de dados* @param sql sql instrutive em @param sql mapper* @param Page Paging Object* @param dialect tipo* @return paging sql* / public static string generpagesql (string sql, página <Objectp. dialect.getlimitString (sql, página.getfirstresult (), página.getMaxResults ()); } else {return sql; }} /*** Remova a cláusula de seleção do QLSTRING. * @param hql * @return */ @suppresswarnings ("não utilizado") String estática privada removeselect (string qlString) {int Beginpos = QlString.TolowerCase (). IndexOf ("de"); retornar QlString.substring (BEGNPOS); } /*** Remova a cláusula de ordem do HQL. *@param hql *@return */string estática privada Remowers (string qlString) {padrony p = padrony.compile ("order // s *por [// w | // w | // s | // s] *", padrony.case_insensitive); Matcher M = P.Matcher (QlString); StringBuffer sb = new StringBuffer (); while (m.find ()) {m.appendReplacement (sb, ""); } M.Appendtail (SB); return sb.toString (); }}Interface dialect.java
pacote com.store.base.secondmodel.base.dialect; / *** semelhante ao hibernado, mas apenas a parte da paginação é simplificada* @author yiyong_wu**/ interface pública dialeto {/ *** O banco de dados suporta o método atual de consulta de paginação/ paging* @Retent* Se o banco de dados não suportará o suporte de datraging)* @return: @return: @suportes* suportes* suporta a datraging cenário / ** * Converta o SQL em SQL de paginação e ligue para a paginação SQL separadamente * * @param SQL SQL Declaração * @param Número de deslocamento de partidas * @param Limite quantos registros são exibidos por página * @return sql para consulta de paginação */ public string getlimstring (string sql, is offset, int limite); }Mysqldialect.java
pacote com.store.base.secondmodel.base.dialect; / ** * Implementação do dialeto mySQL * @author yiyong_wu * */ public class MySqldialect implementa dialeto {@Override public boolean supportLitMit () {return true; } @Override public String getlimitString (String SQL, Int Offset, Int Limit) {return getlimitString (SQL, deslocamento, Integer.toString (Offset), Integer.tostring (limite)); } /*** Transforme o SQL em uma instrução SQL paginada, fornecendo a substituição do deslocamento e o limite pelo espaço reservado. * <pre> * Por exemplo, mysql * dialect.getlimitString ("selecione * do usuário", 12 ": offset", 0, ": limite") retornará * Selecionar * do limite do usuário: deslocamento de limite * </pre> * * @param sql sql sql instrution * @param flaspplate sweotination startinatination pagehold número * @Param Paginação SQL contendo espaço reservado */ public String getlimitString (String SQL, Int Offset, String OffsetPlaceHolder, String LimitplaceHolder) {StringBuilder StringBuilder = new StringBuilder (SQL); stringbuilder.append ("limite"); if (offset> 0) {stringbuilder.append (offsetplaceholder) .Append (","). Append (limitplaceholder); } else {stringbuilder.append (limitplaceholder); } return stringbuilder.toString (); }}Quase aqui compartilhamos como implementar a página inteira, mas temos tarefas mais importantes. Se queremos que tudo seja executado, devemos ter um trabalho básico para fazer. Em seguida, analisamos todo o conjunto de objetos da página e a arquitetura de três camadas em que se baseia e usamos o produto como uma entidade para análise. Depois de falar sobre uma arquitetura completa de três camadas, as recompensas estarão definitivamente cheias. Vamos falar sobre isso na ordem de entidade-> dao-> serviço por sua vez.
Primeiro, devemos herdar duas classes de entidades abstratas e a base de base e a dados para nossas entidades.
BaseEntity.java coloca principalmente a variável de membro da página. Depois de herdá -lo, cada entidade pode ter essa variável de membro.
pacote com.store.base.secondmodel.base; importar java.io.serializable; importar java.util.map; importar javax.xml.bind.annotation.xmltransient; importar org.apache.commons.lang3.StringUtils; importar org.apache.commons.lang3.builder.reflectionToStringBuilder; importar com.fasterxml.jackson.annotation.jsonignore; importar com.google.common.collect.maps; importar com.store.base.model.storeuser; / ** * A entidade de nível superior * @author yiyong_wu * * @param <t> */ public class Baseentity <t> implementa serializável {private estático final serialversionUid = 1L; / ** * Exclua a tag (0: normal; 1: delete; 2: auditoria;) */ public static final string del_flag_normal = "0"; public static final string del_flag_delete = "1"; public static final string del_flag_audit = "2"; / *** Número da entidade (identificador exclusivo)*/ ID da sequência protegida; / *** Usuário atual*/ Protected StoreUser CurrentUser; / *** Objeto de paginação da entidade atual*/ página protegida <t> página; / ** * SQL personalizado (identificador SQL, conteúdo SQL) */ mapa privado <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; } / *** Isso será chamado ao executar atualizações de inserção para Shiro para obter o usuário atual* @return* / @jsonignore @xmltransient public storeUser getCurrentUser () {if (currentUser == null) {// currentUser = userutils.getUser (); } retornar currentUser; } public void setCurrentUser (StoreUser CurrentUser) {this.currentUser = currentUser; } @Jsonignore @xmltransient public Page <T> getPage () {if (página == null) {página = new Page <> (); } página de retorno; } página pública <T> setPage (página <T> página) {this.page = Page; página de retorno; } @Jsonignore @xmlTransient Public Map <String, String> getSqlMap () {if (sqlmap == null) {sqlmap = maps.newhashmap (); } retornar sqlmap; } public void SetsqlMap (map <string, string> sqlmap) {this.sqlmap = sqlmap; } / ** * Execute o método antes da inserção, implementos da subclasse * / public abstrate void preinsert (); / ** * Execute o método antes da atualização, implementos de subclasse */ public abstrato void prepdate (); /*** Seja um novo registro (padrão: false), ligue para o setisNewRecord () para definir um novo registro e usar um ID personalizado. * Depois de definir como True, a instrução Insert é forçada a ser executada. O ID não será gerado automaticamente e precisa ser passado manualmente. * @return */ public boolean getisnewrecord () {return stringUtils.isblank (getId ()); } / *** Objeto variável global* / @jsonignore public Global getGlobal () {return global.getInstance (); } / *** Obtenha o nome do banco de dados* / @jsonignore public string getDbname () {return global.getConfig ("jdbc.type"); } @Override public string tostring () {return refletionToStringBuilder.toString (this); }}DataEntity.java, armazena principalmente o tempo de atualização e exclua, crie usuário, atualize o usuário, sinalizador de deleção lógica, etc.
pacote com.store.base.secondmodel.base; importar java.util.date; importar org.hibernate.validator.constraints.length; importar com.fasterxml.jackson.annotation.jsonformat; importar com.fasterxml.jackson.annotation.jsonignore; importar com.store.base.model.storeuser; / ** * Entidade de dados * @author yiyong_wu * * @param <t> */ public abstrate classe dataentity <t> estende a base de base StoreUser protegido createby; // Data protegida do criador criada; // Data de criação Protected StoreUser Updateby; // Updater Data protegida atualizada; // Data atualizada String protegida Delflag; // Excluir tag (0: normal; 1: excluir; 2: auditoria) public dataEntity () {super (); this.delflag = del_flag_normal; } public dataEntity (string id) {super (id); } / ** * Execute o método antes da inserção, você precisa chamar manualmente * / @Override public void preinsert () {// Nenhuma restrição no ID ao UUID, ligue para setISNewRecord () para usar um ID personalizado // usuário do usuário = userutils.getUser (); // if (stringutils.isnotblank (user.getId ())) {// this.updateby = user; // this.createby = usuário; //} this.UpdateTate = new Date (); this.createdate = this.Updatedate; } / ** * Execute o método antes da atualização, você precisa ligar manualmente * / @Override public void preUpDate () {// Usuário do usuário = 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 (padrony = "yyyy-mm-dd hh: mm: ss") public data getCreatedate () {return criatedate; } public void setCreatedate (data criado) {this.createdate = criatedate; } // @jsonignore public storeUser getUpdateby () {return updateBy; } public void setUpDateBy (StoreUser UpdateBy) {this.UpDateby = updateBy; } @Jsonformat (padrony = "yyyy-mm-dd hh: mm: ss") public date getUpDateate () {return updateTate; } public void setUpDateDate (data atualizada) {this.UpDateTate = atualizada; } @Jsonignore @length (min = 1, max = 1) public string getDelflag () {return delflag; } public void setDelflag (String delflag) {this.delflag = delflag; }}Categoria de produto de produto. Java
pacote com.store.base.secondmodel.pratice.model; importar com.store.base.secondmodel.base.dataentity; / ***Classe básico do produto*11 de outubro de 2016*yiyong_wu*/ public class Product estende a dataentidade <CROTDER> {private estático final serialversionuid = 1L; nome de string privado nome; Preço de flutuação privada; Produto Product String NO; public String getProductName () {return productName; } public void setProductName (String ProductName) {this.productName = productName; } public float getPrice () {Return Price; } public void SetPrice (preço float) {this.price = price; } public string getProductNo () {return productNo; } public void setProductNo (String productNo) {this.productno = productNo; }}Que tal? Você vê um relacionamento de herança de entidade muito complexo? Mas o que há? Quanto mais complexo for, mais completo será. Em seguida, vou olhar para a camada, as mesmas três camadas, prontas para serem batizadas
Interface reservada baseada em java
pacote com.store.base.secondmodel.base; / ** * Interface mais alta Dao * @author yiyong_wu * */ interface pública baseada {} cruddao.java Uma camada de interface Dao para adição, exclusão, modificação e consulta [java] Exibir a impressão de cópia simples? Exibir fragmentos de código no código derivado do meu pacote de fragmentos de código com.store.base.secondmodel.base; importar java.util.list; / ** * Defina a interface Dao para adição, exclusão, modificação e consulta * @author yiyong_wu * * @param <t> */ interface pública cruddao <t> estende baseado em base {/ ** * obtenha uma única peça de dados * @param id * @return */ public t get (string id); / ** * Obtenha uma única peça de dados * @param entidade * @return */ public t Get (t entity); /*** Consulte a lista de dados. Se você precisar de paginação, defina o objeto de paginação, como: entity.setPage (nova página <T> ()); * @param entity * @return */ list public <t> findList (entidade t); / ** * Consulta todos os dados da lista de dados * @param entidade * @return */ list public <t> findAllList (entidade t); /*** Consulta todos os dados da lista* @see Lista pública <T> findAllList (entidade t)* @return Lista pública <T> findAllList (); *// ** * Inserir dados * @param entity * @return */ public int insert (entidade t); / ** * Atualizar dados * @param entity * @return */ public int update (t entity); / ** * Excluir dados (geralmente exclusão lógica, atualize o campo del_flag para 1) * @param id * @see public int Delete (entidade t) * @return */ public int Delete (string id); / ** * Excluir dados (geralmente a deleção lógica, atualize o campo del_flag para 1) * @param entity * @return */ public int excluir (entidade t); }ProductDao.java mybatis O Mapper de interface correspondente também é uma implementação DAO. Você precisa personalizar a anotação @mybatisrepository
pacote com.store.base.secondmodel.pratice.dao; importar com.store.base.secondmodel.base.cruddao; importar com.store.base.secondmodel.base.mybatisrepository; importar com.store.base.secondmodel.pratice.model.product; / ** *TODO *11 de outubro de 2016 *yiyong_wu */ @mybatisRepository interface pública ProductDao estende Cruddao <Product> {}Anotação personalizada mybatisrepository.java está relacionada à anotação personalizada. Não vou explicar muito aqui, há muitas informações on -line.
pacote com.store.base.secondmodel.base; importar java.lang.annotation.Documented; importar java.lang.annotation.retention; importar java.lang.annotation.target; importar java.lang.annotation.retEntionPolicy; importar java.lang.annotation.ElementType; importar org.springframework.tereotype.component; /*** Identifique o Dao de Mybatis para facilitar a digitalização de {@link org.mybatis.spring.mapper.mapperscannerConfigurer}. * *Observe que deseja configurar a configuração para digitalizar a classe anotada no arquivo de configuração da mola * *<bean id = "mapperscannerConfigurer"> *<nome da propriedade "SQLSessionFactoryBeanName" Value = "sqlSessionFactory" /> *<Nome da propriedade "" BasePackage "Value =" Comm. " name = "annotationClass" value = "com.store.base.secondmodel.base.mybatisrepositor padrão ""; } Nota: O arquivo ProductMapper.xml que possui uma forte conexão com o ProductDAO.java é o arquivo productmapper.xml. Você pode ver que o espaço para nome do arquivo de configuração acima aponta para o caminho para este DAO.
Em seguida, entramos na análise de serviço final e também é uma herança de três camadas.
BaseService.java
pacote com.store.base.secondmodel.base; importar org.slf4j.logger; importar org.slf4j.loggerFactory; importar org.slf4j.loggerFactory; importar org.springframework.transaction.annotation.transaction; / ** * A classe de serviço pai de nível superior * @author yiyong_wu * */ @transaction (readOnly = true) classe public abstract Class BaseService {// Logger protegido = LoggerFactory.getLogger (getClass ()); }Implementação de interface de negócios relacionada a CrudService.java
pacote com.store.base.secondmodel.base; importar java.util.list; importar org.springframework.beans.factory.annotation.autowired; importar org.springframework.transaction.annotation.transaction; / ** * Adicione, exclua, modifique e verifique a classe Base de serviço * @Author yiyong_wu * * @param <d> * @param <t> */ public abstrate classe crudservice <d estende Cruddao <t>, t estende a datantity <T >> estende o BasEstice {/ ** * persistency; / ** * Obtenha uma única peça de dados * @param id * @return */ public t get (string id) {return Dao.get (id); } / ** * Obtenha uma única peça de dados * @param entidade * @return * / public t get (t entity) {return Dao.get (entidade); } /** * 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; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.annotation.JsonIgnore; import com.store.base.secondmodel.base.util.CookieUtils; import com.store.base.secondmodel.base.util.StringUtils; /** * 分页类* @author yiyong_wu * * @param <T> */ public class Page<T> implements Serializable{ private static final long serialVersionUID = 1L; private int pageNo = 1; // 当前页码private int pageSize = Integer.parseInt(Global.getConfig("page.pageSize")); // 页面大小,设置为“-1”表示不进行分页(分页无效) private long count;// 总记录数,设置为“-1”表示不查询总数private int first;// 首页索引private int last;// 尾页索引private int prev;// 上一页索引private int next;// 下一页索引private boolean firstPage;//是否是第一页private boolean lastPage;//是否是最后一页private int length = 6;// 显示页面长度private int slider = 1;// 前后显示页面长度private List<T> list = new ArrayList<>(); private String orderBy = ""; // 标准查询有效, 实例: updatedate desc, name asc private String funcName = "page"; // 设置点击页码调用的js函数名称,默认为page,在一页有多个分页对象时使用。 private String funcParam = ""; // 函数的附加参数,第三个参数值。 private String message = ""; // 设置提示消息,显示在“共n条”之后public Page() { this.pageSize = -1; } /** * 构造方法* @param request 传递repage 参数,来记住页码* @param response 用于设置Cookie,记住页码*/ public Page(HttpServletRequest request, HttpServletResponse response){ this(request, response, -2); } /** * 构造方法* @param request 传递repage 参数,来记住页码* @param response 用于设置Cookie,记住页码* @param defaultPageSize 默认分页大小,如果传递-1 则为不分页,返回所有数据*/ public Page(HttpServletRequest request, HttpServletResponse response, int defaultPageSize){ // 设置页码参数(传递repage参数,来记住页码) 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)); } } // 设置页面大小参数(传递repage参数,来记住页码大小) 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; } // 设置排序参数String orderBy = request.getParameter("orderBy"); if (StringUtils.isNotBlank(orderBy)){ this.setOrderBy(orderBy); } } /** * 构造方法* @param pageNo 当前页码* @param pageSize 分页大小*/ public Page(int pageNo, int pageSize) { this(pageNo, pageSize, 0); } /** * 构造方法* @param pageNo 当前页码* @param pageSize 分页大小* @param count 数据条数*/ public Page(int pageNo, int pageSize, long count) { this(pageNo, pageSize, count, new ArrayList<T>()); } /** * 构造方法* @param pageNo 当前页码* @param pageSize 分页大小* @param count 数据条数* @param list 本页数据对象列表*/ public Page(int pageNo, int pageSize, long count, List<T> list) { this.setCount(count); this.setPageNo(pageNo); this.pageSize = pageSize; this.list = list; } /** * 初始化参数*/ 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) {// 如果当前页小于首页this.pageNo = this.first; } if (this.pageNo > this.last) {// 如果当前页大于尾页this.pageNo = this.last; } } /** * 默认输出当前分页标签* <div>${page}</div> */ @Override public String toString() { StringBuilder sb = new StringBuilder(); if (pageNo == first) {// 如果是首页sb.append("<li class=/"disabled/"><a href=/"javascript:/">« 上一页</a></li>/n"); } else { sb.append("<li><a href=/"javascript:/" onclick=/""+funcName+"("+prev+","+pageSize+",'"+funcParam+"');/">« 上一页</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:/">下一页»</a></li>/n"); } else { sb.append("<li><a href=/"javascript:/" onclick=/""+funcName+"("+next+","+pageSize+",'"+funcParam+"');/">" + "下一页»</a></li>/n"); } return sb.toString(); } /** * 获取分页HTML代码* @return */ public String getHtml(){ return toString(); } /** * 获取设置总数* @return */ public long getCount() { return count; } /** * 设置数据总数* @param count */ public void setCount(long count) { this.count = count; if (pageSize >= count){ pageNo = 1; } } /** * 获取当前页码* @return */ public int getPageNo() { return pageNo; } /** * 设置当前页码* @param pageNo */ public void setPageNo(int pageNo) { this.pageNo = pageNo; } /** * 获取页面大小* @return */ public int getPageSize() { return pageSize; } /** * 设置页面大小(最大500)// > 500 ? 500 : pageSize; * @param pageSize */ public void setPageSize(int pageSize) { this.pageSize = pageSize <= 0 ? 10 : pageSize; } /** * 首页索引* @return */ @JsonIgnore public int getFirst() { return first; } /** * 尾页索引* @return */ @JsonIgnore public int getLast() { return last; } /** * 获取页面总数* @return getLast(); */ @JsonIgnore public int getTotalPage() { return getLast(); } /** * 是否为第一页* @return */ @JsonIgnore public boolean isFirstPage() { return firstPage; } /** * 是否为最后一页* @return */ @JsonIgnore public boolean isLastPage() { return lastPage; } /** * 上一页索引值* @return */ @JsonIgnore public int getPrev() { if (isFirstPage()) { return pageNo; } else { return pageNo - 1; } } /** * 下一页索引值* @return */ @JsonIgnore public int getNext() { if (isLastPage()) { return pageNo; } else { return pageNo + 1; } } /** * 获取本页数据对象列表* @return List<T> */ public List<T> getList() { return list; } /** * 设置本页数据对象列表* @param list */ public Page<T> setList(List<T> list) { this.list = list; initialize(); return this; } /** * 获取查询排序字符串* @return */ @JsonIgnore public String getOrderBy() { // SQL过滤,防止注入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; } /** * 设置查询排序,标准查询有效, 实例: updatedate desc, name asc */ public void setOrderBy(String orderBy) { this.orderBy = orderBy; } /** * 获取点击页码调用的js函数名称* function ${page.funcName}(pageNo){location="${ctx}/list-${category.id}${urlSuffix}?pageNo="+i;} * @return */ @JsonIgnore public String getFuncName() { return funcName; } /** * 设置点击页码调用的js函数名称,默认为page,在一页有多个分页对象时使用。 * @param funcName 默认为page */ public void setFuncName(String funcName) { this.funcName = funcName; } /** * 获取分页函数的附加参数* @return */ @JsonIgnore public String getFuncParam() { return funcParam; } /** * 设置分页函数的附加参数* @return */ public void setFuncParam(String funcParam) { this.funcParam = funcParam; } /** * 设置提示消息,显示在“共n条”之后* @param message */ public void setMessage(String message) { this.message = message; } /** * 分页是否有效* @return this.pageSize==-1 */ @JsonIgnore public boolean isDisabled() { return this.pageSize==-1; } /** * 是否进行总数统计* @return this.count==-1 */ @JsonIgnore public boolean isNotCount() { return this.count==-1; } /** * 获取Hibernate FirstResult */ public int getFirstResult(){ int firstResult = (getPageNo() - 1) * getPageSize(); if (firstResult >= getCount()) { firstResult = 0; } return firstResult; } /** * 获取Hibernate MaxResults */ public int getMaxResults(){ return getPageSize(); } }看完这个Page对象应该稍微有点感觉了吧,然后我在胡乱贴一些相关用到的工具类吧,工具类的话我只稍微提一下,具体大家可以弄到自己的代码上好好解读。
PropertiesLoader.java 用来获取resource文件夹下的常量配置文件
package com.store.base.secondmodel.base.util; import java.io.IOException; import java.io.InputStream; import java.util.NoSuchElementException; import java.util.Properties; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; /** * Properties文件载入工具类. 可载入多个properties文件, * 相同的属性在最后载入的文件中的值将会覆盖之前的值,但以System的Property优先. * @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; } /** * 取出Property,但以System的Property优先,取不到返回空字符串. */ private String getValue(String key) { String systemProperty = System.getProperty(key); if (systemProperty != null) { return systemProperty; } if (properties.containsKey(key)) { return properties.getProperty(key); } return ""; } /** * 取出String类型的Property,但以System的Property优先,如果都为Null则抛出异常. */ public String getProperty(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return value; } /** * 取出String类型的Property,但以System的Property优先.如果都为Null则返回Default值. */ public String getProperty(String key, String defaultValue) { String value = getValue(key); return value != null ? value : defaultValue; } /** * 取出Integer类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常. */ public Integer getInteger(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return Integer.valueOf(value); } /** * 取出Integer类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常*/ public Integer getInteger(String key, Integer defaultValue) { String value = getValue(key); return value != null ? Integer.valueOf(value) : defaultValue; } /** * 取出Double类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常. */ public Double getDouble(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return Double.valueOf(value); } /** * 取出Double类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常*/ public Double getDouble(String key, Integer defaultValue) { String value = getValue(key); return value != null ? Double.valueOf(value) : defaultValue.doubleValue(); } /** * 取出Boolean类型的Property,但以System的Property优先.如果都为Null抛出异常,如果内容不是true/false则返回false. */ public Boolean getBoolean(String key) { String value = getValue(key); if (value == null) { throw new NoSuchElementException(); } return Boolean.valueOf(value); } /** * 取出Boolean类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容不为true/false则返回false. */ public Boolean getBoolean(String key, boolean defaultValue) { String value = getValue(key); return value != null ? Boolean.valueOf(value) : defaultValue; } /** * 载入多个文件, 文件路径使用Spring Resource格式. */ private Properties loadProperties(String... resourcesPaths) { Properties props = new Properties(); for (String location : resourcesPaths) { InputStream is = null; try { Resource resource = resourceLoader.getResource(location); is = resource.getInputStream(); props.load(is); } catch (IOException ex) { logger.error("Could not load properties from path:" + location , ex); } finally { IOUtils.closeQuietly(is); } } return props; } }Global.java 用来获取全局的一些常量,可以是从配置文件中读取的常量,也可以是定义成final static的常量,获取配置文件的话是调用上面那个类进行获取的。
package com.store.base.secondmodel.base; import java.io.File; import java.io.IOException; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.DefaultResourceLoader; import com.google.common.collect.Maps; import com.store.base.secondmodel.base.util.PropertiesLoader; import com.store.base.secondmodel.base.util.StringUtils; /** * 全局配置类* @author yiyong_wu * */ public class Global { private static final Logger logger = LoggerFactory.getLogger(Global.class); /** * 当前对象实例*/ private static Global global = new Global(); /** * 保存全局属性值*/ private static Map<String, String> map = Maps.newHashMap(); /** * 属性文件加载对象*/ private static PropertiesLoader loader = new PropertiesLoader("application.properties"); /** * 显示/隐藏public static final String SHOW = "1"; public static final String HIDE = "0"; /** * 是/否*/ public static final String YES = "1"; public static final String NO = "0"; /** * 状态上/下app专用*/ public static final String UPSHVELF = "1"; public static final String DOWNSHVELF = "2"; public static final String SEPARATOR = "/"; /** * 对/错*/ public static final String TRUE = "true"; public static final String FALSE = "false"; /** * 上传文件基础虚拟路径*/ public static final String USERFILES_BASE_URL = "/userfiles/"; /** * 针对富文本编辑器,结尾会产生的空div */ public static final String ENDS = "<p><br></p>"; /** * 默认空的私有构造函数*/ public Global() { //do nothing in this method,just empty } /** * 获取当前对象实例*/ public static Global getInstance() { return global; } /** * 获取配置*/ 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; } /** * 获取URL后缀*/ public static String getUrlSuffix() { return getConfig("urlSuffix"); } /** * 页面获取常量* @see ${fns:getConst('YES')} */ public static Object getConst(String field) { try { return Global.class.getField(field).get(null); } catch (Exception e) { logger.error("获取常量出错", e); } return null; } /** * 获取工程路径* @return */ public static String getProjectPath(){ // 如果配置了工程路径,则直接返回,否则自动获取。 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("加载配置文件失败", e); } return projectPath; } }CookieUtil.java 从名称就知道是针对获取和存储cookie的一个工具类
package com.store.base.secondmodel.base.util; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Cookie工具类* @author yiyong_wu * */ public class CookieUtils { private static final Logger logger = LoggerFactory.getLogger(CookieUtils.class); /** * 私有构造函数*/ private CookieUtils() { } /** * 设置Cookie(生成时间为1年) * @param name 名称* @param value 值*/ public static void setCookie(HttpServletResponse response, String name, String value) { setCookie(response, name, value, 60*60*24*365); } /** * 设置Cookie * @param name 名称* @param value 值* @param maxAge 生存时间(单位秒) * @param uri 路径*/ public static void setCookie(HttpServletResponse response, String name, String value, String path) { setCookie(response, name, value, path, 60*60*24*365); } /** * 设置Cookie * @param name 名称* @param value 值* @param maxAge 生存时间(单位秒) * @param uri 路径*/ public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) { setCookie(response, name, value, "/", maxAge); } /** * 设置Cookie * @param name 名称* @param value 值* @param maxAge 生存时间(单位秒) * @param uri 路径*/ 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("不支持的编码", e); } response.addCookie(cookie); } /** * 获得指定Cookie的值* @param name 名称* @return 值*/ public static String getCookie(HttpServletRequest request, String name) { return getCookie(request, null, name, false); } /** * 获得指定Cookie的值,并删除。 * @param name 名称* @return 值*/ public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name) { return getCookie(request, response, name, true); } /** * 获得指定Cookie的值* @param request 请求对象* @param response 响应对象* @param name 名字* @param isRemove 是否移除* @return 值*/ 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("不支持的编码", 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; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringEscapeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.LocaleResolver; import com.store.base.util.Encodes; /** * 字符串帮助类* @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); /** * 转换为字节数组* @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]; } } /** * 转换为字节数组* @param str * @return */ public static String toString(byte[] bytes){ try { return new String(bytes, CHARSET_NAME); } catch (UnsupportedEncodingException e) { logger.error("", e); return EMPTY; } } /** * 是否包含字符串* @param str 验证字符串* @param strs 字符串组* @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; } /** * 替换掉HTML标签方法*/ 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(""); } /** * 替换为手机识别的HTML,去掉样式及属性,保留回车。 * @param html * @return */ public static String replaceMobileHtml(String html){ if (html == null){ return ""; } return html.replaceAll("<([az]+?)//s+?.*?>", "<$1>"); } /** * 替换为手机识别的HTML,去掉样式及属性,保留回车。 * @param txt * @return */ public static String toHtml(String txt){ if (txt == null){ return ""; } return replace(replace(Encodes.escapeHtml(txt), "/n", "<br/>"), "/t", " "); } /** * 缩略字符串(不区分中英文字符) * @param str 目标字符串* @param 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("..."); break; } } return sb.toString(); } catch (UnsupportedEncodingException e) { logger.error("", e); } return ""; } /** * 转换为Double类型*/ 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; } } /** * 转换为Float类型*/ public static Float toFloat(Object val){ return toDouble(val).floatValue(); } /** * 转换为Long类型*/ public static Long toLong(Object val){ return toDouble(val).longValue(); } /** * 转换为Integer类型*/ public static Integer toInteger(Object val){ return toLong(val).intValue(); } /** * 获得i18n字符串*/ 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); } /** * 获得用户远程地址*/ 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(); } /** * 驼峰命名法工具* @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(); } /** * 驼峰命名法工具* @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); } /** * 驼峰命名法工具* @return * toCamelCase("hello_world") == "helloWorld" * toCapitalizeCamelCase("hello_world") == "HelloWorld" * toUnderScoreCase("helloWorld") = "hello_world" */ public static String toUnderScoreCase(String s) { if (s == null) { return null; } StringBuilder sb = new StringBuilder(); boolean upperCase = false; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); boolean nextUpperCase = true; if (i < (s.length() - 1)) { nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); } if ((i > 0) && Character.isUpperCase(c)) { if (!upperCase || !nextUpperCase) { sb.append(SEPARATOR); } upperCase = true; } else { upperCase = false; } sb.append(Character.toLowerCase(c)); } return sb.toString(); } /** * 转换为JS获取对象值,生成三目运算返回结果* @param objectString 对象串* 例如:row.user.id * 返回:!row?'':!row.user?'':!row.user.id?'':row.user.id */ public static String jsGetVal(String objectString){ StringBuilder result = new StringBuilder(); StringBuilder val = new StringBuilder(); String[] vals = split(objectString, "."); for (int i=0; i<vals.length; i++){ val.append("." + vals[i]); result.append("!"+(val.substring(1))+"?'':"); } result.append(val.substring(1)); return result.toString(); } }有了上面这些基础的东西,只需要在写一个控制层接口,就可以看到每次返回一个page对象,然后里面封装好了查询对象的列表,并且是按分页得出列表。
package com.store.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.store.base.secondmodel.base.Page; import com.store.base.secondmodel.pratice.model.Product; import com.store.base.secondmodel.pratice.service.ProductService; /** *TODO *2016年10月11日*yiyong_wu */ @RestController @RequestMapping("/product") public class ProductController { @Autowired private ProductService productService; @ResponseBody @RequestMapping(value="/getPageProduct") public Page<Product> getPageProduct(HttpServletRequest request,HttpServletResponse response){ Page<Product> page = productService.findPage(new Page<Product>(request,response), new Product()); return page; } }最后在看一下页面怎么使用这个page对象,这样我们就完整地介绍了这个一个分页功能,代码很多,但很完整。
<%@ page contentType="text/html;charset=UTF-8"%> <%@ include file="/WEB-INF/views/include/taglib.jsp"%> <html> <head> <title></title> <meta name="decorator" content="default" /> function page(n, s) { if (n) $("#pageNo").val(n); if (s) $("#pageSize").val(s); $("#searchForm").attr("action", "${ctx}/app/bank/list"); $("#searchForm").submit(); return false; } </script> </head> <body> <form:form id="searchForm" modelAttribute="XXXX" action="${ctx}/XXX" method="post"> <input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}" /> <input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}" /> <ul> <li> <label>是否上架:</label> <form:select id="status" path="status"> <form:option value="" label=""/> <form:options items="${fns:getDictList('yes_no_app')}" itemLabel="label" itemValue="value" htmlEscape="false"/> </form:select> </li> <li><input id="btnSubmit" type="submit" value="查询"/> <li></li> </ul> </form:form> <sys:message content="${message}" /> <sys:message content="${message}" /> <table id="contentTable"> <thead> <tr> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> <th>XXXX</th> </tr> </thead> <tbody> <c:forEach items="${page.list}" var="XXXX"> <tr> <td>${XXXX.name}</td> <td><a href="${ctx}/app/bank/form?id=${XXXX.id}">${XXXX.}</a></td> <td>${XXXX.}</td> <td>${XXXX.}</td> <td>${XXXX.}</td> <td>${fns:getDictLabel(XXXX.isHot, 'yes_no_app', '无')}</td> <td>${XXXX.}</td> <td><c:if test="${XXXX.status==1 }">上架</c:if> <c:if test="${XXXX.status==2 }">下架</c:if> </td> </tr> </c:forEach> </tbody> </table> <div>${page} <li style="padding-top: 6px;padding-left: 12px;float: left;">共${page.count}条</li></div> </body> </html>到这里就基本上把整个分页功能描述得比较清楚了,希望可以帮助到你们快速解决分页这个问题,当然要在前端显示分页漂亮的话要针对li做一些css样式啥的,最后祝福你可以快速掌握这个分页功能!
以上所述是小编给大家介绍的Mybatis常用分页插件实现快速分页处理技巧,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!