Este blog apresenta a função de paginação com base na estrutura ORM da Spring Data, mais o plug-in jQuery.Pagination.
Este blog é baseado em um projeto de código aberto do GitHub em desenvolvimento. O endereço do código do projeto é: https://github.com/u014427391/jeepatform
Bem -vindo ao Star (coleção) ou download para aprender, e ainda está se desenvolvendo ...
Introduzir a estrutura de dados da primavera
Dados da mola: um subprojeto da mola. Usado para simplificar o acesso e suportar o NOSQL e o armazenamento de dados relacionais.
A seguir, o armazenamento NOSQL suportado pelo Projeto Springdata:
* MongoDB (banco de dados de documentos)
* NEO4J (banco de dados gráfico)
* Redis (loja de chave/valor)
* HBASE (Banco de Dados da Família da Coluna)
Tecnologias relacionais de armazenamento de dados suportadas pelos projetos SpringData:
* JDBC
* Jpa
JPA Spring Data: dedicado a reduzir o volume de desenvolvimento da camada de acesso a dados (DAO). Os desenvolvedores precisam apenas escrever a interface da camada de persistência e, em seguida, outras estruturas ajudarão os programadores a implementá -los.
Etapas de desenvolvimento:
Spring Data Data implementa a aquisição de dados】
Este projeto usa o MAVEN, para que você possa consultar minha configuração do Maven:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd "> <aporel> <ArtifactId> musas </stutifactId> <voupid> org.muses </roupidId> <Versão> 1.0-snapshot </sipers> </parent> <lodelVersion> 4.0.0 </Modelssion> <TarifactId> jeepartform-admin </stutifactId> <batyaging> war </acheging> <name> jeepartform-admin maven webapp </name> <url> http://maven.apache.org </url> <springs> <pringersion> 4.1.5. <fring-data-jpa.version> 1.4.2.Release </spring-data-jpa.version> <spring-data-commons.version> 1.6.2.Release </spring-data-commons.version> <hibernate.version> 4.3.8.Final </hibernate.version> <hir3 <Cune.Version> 4.7.2 </lucene.version> <druid.version> 1.0.9 </druid.version> <poi.version> 3.7 </poi.version> </mperties> </dependências> <!-start-> <peDency> <purful> ourg.muses </GrupoIdId> Artif> <! <versão> $ {jeepatform.core.version} </version> </dependency> <pendence> <puperid> org.muses </groupiD> <TRARFACTID> jeepatform-common </sutifactid> <Versão> 1.0-snapshot </sipers> </spendence> <pendence> <urpuld> ou. <TarifactId> jeepatform-sS </ArtifactId> <versão> $ {jeepatform.oss.version} </version> </dependency> <pendecency> <puperid> org.muses <-ende! START-> <Depency> <PuerpId> javax.servlet </groupId> <TROTIFACTID> servlet-api </artifactId> <versão> 2.5 </versão </scope> fornecido </scope> </dependency> <!-ENVERT END-> <!-JSTL-> <Depency> <purtEncy> jStl </groupd) </groupId art. <Version> 1.2 </sistER> </dependency> <pendence> <puperid> taglibs </groupiD> <TRAFACTID> padrão </ArtifactId> <versão> 1.1.2 </versão> </dependency> <!-jstl end-> <!-log4j start-> <pendency> <broupid> <! <Versão> $ {log4j.version} </sistER> </dependency> <!-log4j end-> <!-JSON Animação de jar obrigatória Iniciar-> <Depency> <puperid> commons-beanutils </groupId> <sutifactId> commons-beanutils </Artifactid> </siperid> </versão <GrupID> Commons-Collections </GroupId> <stifactId> Commons-Collections </ArtifactId> <versão> 3.2.1 </versão> </dependency> <pendence> <purpuld> net.sf.ezmorph </groupid> <TRAFACTID> ezmorph </artifactid> <versão 1.0 1.0.6 </groupid> <PuerpId> Commons-lang </frupiD> <ArtifactId> Commons-Lang </ArtifactId> <Version> 2.5 </version> </dependency> <pendence-> <puperid> commons-logging </groupid> </dependência> commons-logging </artifactId> <siper> 1.2 </versão </dependência> </dependência> <stifactId> JSON-LIB </ArtifactId> <versão> 2.4 </version> <type> jar </pype> <ldesifier> jdk15 </slesfier> <scope> compilação </scope> </dependency> <!-end end para JSON Parsing-> <!-mysql start-> <pendence> <! </ArtifactId> <versão <Depencency> <PuerpId> Commons-FileUpload </GroupId> <TRAFACTID> Commons-FileUpload </stutifactId> <versão> 1.2.2 </versão> </dependency> <!-commons-> <!-Spring Framework Start-> <Depency> <Grupid> Org.SpringFortHortwid> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <TRAFACTID> Spring-Context </ArtifactId> <versão> $ {spring.version} </version> </dependency> <pendence-> <voundid> org.springframework </purbrouid> <sepifactId> Spring-Context-suporp </ArtifactId> <versão> dependente> Spring.version} <GrupidId> org.springframework </frugiD> <TRAFACTID> spring-jdbc </artifactId> <versão> $ {spring.version} </versão> </dependency> <pendency> <broupId> org.springframework </groupid> <ArtifactId> Spring-tx </artef <Depencency> <PuerpId> org.springframework </frugiD> <ArtifactId> Spring-test </ArtifactId> <versão> $ {spring.version} </sipers> <cope> teste </scope> </dependence> <pendency> <pringa> org.springFramewring </propiD> <stifact> <versão> $ {spring.version} </version> </dependency> <!-Spring Framework End-> <!-Spring AOP START-> <Ependency> <Groupid> org.springframework </roupidId> <rutifactId> spring-aop </stifactid> <versão> {spring.version} </versão> <TRATIFACTID> AspectJweaver </storkactId> <versão> 1.6.10 </versão> </dependency> <!-Spring AOP End-> <!-Springmvc START-> <Depence> <Prochaid> Org.springFramework </groupId> <tifactId> Spring-Webmvc </ArtifactIrkwork> <!-springmvc end-> <!-Spring Data Start-> <pendency> <voundid> org.springframework </frugiD> <ArtifactId> spring -form </stutifactId> <sipers <TRAFACTID> Spring-Data-jpa </ArtifactId> <Versão> $ {Spring-Data-Jpa.version} </Version> </Dependency> <pendency> <puriDiD> org.springframework.data </groupid> <ArtifactId> spring-data-concommons </artefactid> </dependency> <!-- spring data end --> <!-- hibernate jpa start--> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.1-api</artifactId> <version>1.0.0.Final</version> </dependency> <dependency> <PuerpId> org.hibernate </frugiD> <TRAFACTID> hibernate-core </stutifactId> <versão> $ {hibernate.version} </version> </dependency> <pendency> <purpuld> org. </dependency> <!-hibernate jpa end-> <!-hibernate echache start-> <pendency> <puperid> org.slf4j </groupiD> <TRAFACTID> slf4j-api </artifactId> <versão> 1.6.1 </version> </dependence> <purfiDid> <TarifactId> ehcache-core </starifactId> <versão> 2.5.0 </versão> </dependency> <pendency> <puperid> org.hibernate </groupiD> <TRARFACTID> hibernate-ehcache </artifactid> <versão> {hibernate.version} </versão> Druida de pool de conexão do Alibaba Iniciar-> <Depence> <puperiD> com.alibaba </groupId> <TRarifactId> druid </artifactId> <versão> $ {druid.version} </versão> </dependency> <!-Aliba's Connection Pool-endern-!-Ternate iDernate iCHACHE ICHACH-HIBERNATE ICHACHT: HIBERNATE ICHACHT: Hibernate Echache End-> <!-Alibaba Pool de conexão Druid End-> <!-Shiro Start-> <Depency> <PuerpId> org.apache.shiro </groupiD> <ArtifactId> Shiro-All </Artifactid> <versão> $ {shiro.version} </versão> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-tools</artifactId> <version>2.0</version> </dependency> <!-- velocity end--> <!-Lucene TEXTO DE TEXTO COMPLETO DO MOTOR DE TEXTO DE início-> <Ependency> <Puperid> org.apache.lucene </groupiD> <TorifactId> Lucene-core </sutifactId> <versão> $ {Lucene.version} </sipers> </pendence> <pendency> <purbumid> org.apache.lune </Gruperid> <TarifactId> Lucene-analisadores-common </stifactId> <versão> $ {Lucene.version} </versão> </dependency> <pendency> <puerpiD> org.apache.lucene </groupid> <stifactId> Lucene-quanterser </ArtifactId> <ersiSSERS> $ { <PuerpId> org.apache.luceno </frupiD> <TRAFACTID> Lucene-meseiRy </storkactId> <versão> $ {Lucene.version} </Version> </dependency> <pendency> <purpacherktymatty) <sberssion> <bumssion> org.apache.lucene </groupid> <TifactId>) {Lucene)) </dependency> <!-Observe que o ikanalyzer não possui coordenadas do MAVEN, adicione-as ao repositório local-> <Depencency> <roupidId> org.wltea.analyzer </groupid> <sutifactId> ikanalyzer </artifactid> </uplys> 2012ff_u1 </versão> <SystemPath> $ {baseado} /src/main/webapp/web-inf/lib/ikanalyzer2012ff_u1.jar </systempath> </dependency> <!-Lucene Pesquisa completa mecanismo final-> <!-log4j start-> <pendency> <broupId> log4j </Grupoid> <Versão> $ {log4j.version} </sistER> </dependency> <!-log4j end-> <!-JSON Animação de jar obrigatória Iniciar-> <Depency> <puperid> commons-beanutils </groupId> <sutifactId> commons-beanutils </Artifactid> </siperid> </versão <GrupID> Commons-Collections </GroupId> <stifactId> Commons-Collections </ArtifactId> <versão> 3.2.1 </versão> </dependency> <pendence> <purpuld> net.sf.ezmorph </groupid> <TRAFACTID> ezmorph </artifactid> <versão 1.0 1.0.6 </groupid> <PuerpId> Commons-lang </frupiD> <ArtifactId> Commons-Lang </ArtifactId> <Version> 2.5 </version> </dependency> <pendence-> <puperid> commons-logging </groupid> </dependência> commons-logging </artifactId> <siper> 1.2 </versão </dependência> </dependência> <TeRtifactId> JSON-LIB </ArtifactId> <versão> 2.4 </version> <type> jar </pype> <sclassifier> jdk15 </classifier> <cope> compile </scope> </dependency> <!-JSON Parsing Jar End-> <!-POI start-> <Pendence> <ArtifactId> poi </stifactId> <versão> $ {poi.version} </versão> </dependency> <!-poi end-> <!-email start-> <pendency> <puidid> com.sun.mail </groupid> <stifactId> javax.mail </stifactid> versão </groupid> <Build> <finname> jeepatform-admin </finalname> </fruct> </jur Project> Projete o banco de dados e escreva uma classe de entidade:
pacote org.muses.jeepAtform.model.entity; importar java.util.date; importar java.util.set; importar javax.persistence.cascadeType; import javax.persistence.column; importStorx.persistence.Imity; javax.persistence.generationType; importar javax.persistence.id; importar javax.persistence.Joincolumn; importar javax.persistence.Jointable; import javax.persistence.persistence.tomany; importer.persistence.table; importação; javax.persistence.TemporalType;/***Classe de entidade de informações do usuário*@author nicky*/@entity@tabela (name = "sys_user") public class Usuário {/** ID do usuário **/private int id; / ** Nome de usuário **/ nome de string privado nome de usuário; / ** Senha do usuário **/ senha de sequência privada; / ** Número do telefone celular **/ telefone privado int; / ** gênero **/ sexo privado de cordas; / ** E -mail **/ email de sequência privada; / ** Nota **/ Private String Mark; / ** Nível do usuário **/ String privada classificação; / ** Última vez **/ data privada lastLogin; / ** Login ip **/ private string loginip; / ** Caminho da imagem **/ private string imageurl; / ** Tempo de registro **/ data privada regtime; / ** se a conta está bloqueada **/ private boolean bloqueado = boolean.false; Participação de Conjunto Privado <Role>; @GeneratedValue (estratégia = generationType.Identity) @id public int getId () {return id; } public void setId (int id) {this.id = id; } @Column (exclusivo = true, length = 100, nullable = false) public string getUserName () {return userName; } public void setUserName (string userName) {this.username = nome de usuário; } @Column (length = 100, nullable = false) public string getPassword () {return senha; } public void setPassword (string senha) {this.password = senha; } public int getPhone () {return telefone; } public void setphone (int telefone) {this.phone = telefone; } @Column (comprimento = 6) public string getSex () {return Sex; } public void SetSex (sexo de string) {this.sex = sexo; } @Column (length = 100) public string getemail () {return email; } public void setEmail (string email) {this.email = email; } @Column (length = 30) public string getmark () {return mark; } public void Setmark (string mark) {this.mark = mark; } @Column (length = 10) public string getRank () {return rank; } public void setRank (string rank) {this.rank = rank; } @Temporal (temporalType.date) data public getLastLogin () {return lastLogin; } public void setLastLogin (date lastLogin) {this.LastLogin = lastLogin; } @Column (length = 100) public string getLoginip () {return Loginip; } public void setLoginip (string loginip) {this.loginip = loginip; } @Column (length = 100) public string getImageurl () {return imageurl; } public void setImageUrl (string imageurl) {this.imageurl = imageurl; } @Temporal (temporalType.date) @column (nullable = false) date getRegtime () {return regtime; } public void setRegtime (date regtime) {this.regtime = regtime; } public boolean getLocked () {return bloqueado; } public void Setlocked (bloqueado booleano) {this.locked = bloqueado; }}Interface de gravação para implementar a interface PagingAndSortingRepository da estrutura de dados da mola
pacote org.muses.jeepartform.repository; importar org.muses.jeepartform.model.entity.user; importar org.springframework.data.domain.page; import org.springframework.data.domain.pageabe; org.springframework.data.jpa.repository.jparepository; importar org.springframework.data.repository.querery; importar org.springframework.data.repository.pagingandsortingRepository; import.springfringflata.data.data.data.data.data.data.data.DagingAndsortingRepositório java.util.date; interface pública UserRepository estende o PagingAndSortingRepository <Usuário, Integer> { /*User FindByuserName (String UserName); @Query ("do usuário u onde u.UserName =: nome de usuário e u.password =: senha") Usuário findbyusernameandpassword (@param ("nome de usuário") string username, @param ("senha") string senha); @Query ("do usuário u onde u.id =: id") usuário findbyid (@param ("id") int id); @Query ("do usuário u onde Date_format (U.LastLogin, 'AAAYYY-MM-DD') entre Date_Format ((: StartDate), 'yyyyy-mm-dd') e date_format ((: enddate), 'yyyy-mm-dd') date) date <userem> (@Param (" Dateam), "yyyyy-mm-dd")) página <userve> ("@param (" Pagável);*/}Implementação de classe executiva:
pacote org.muses.jeepatform.service; importar java.util. org.springframework.data.domain.page; importar org.springframework.data.domain.pagerequest; importar org.springframework.data.domain.sort; importar org.springframework.data.jpa.domet.sort; importação; org.springframework.transaction.annotation.transaction; importar javax.persistence.criteria.criteriabuilder; importar javax.persistence.criteria.criteriaQuery;/** *** @Description userRepository; / ** * Construa o objeto PageReQuest * @param num * @param tamanho * @param asc * @param string * @return */ private pagerequest BuildPageRequest (int num, int size, sort.direction ASC, string string) {retorna o novo pagerequest (num-1, tamanho, nulo, string); } / *** Obtenha todas as informações do menu e exibi -las nas páginas* @param pageno* número atual de páginas* @param pagageSize* Número de páginas por página* @return* / @Transaction Public Page <usery> findAll (Int Pageno, Pagesize, Sort.Direction Dir, string), PagereQuest = BuiltPenO, Pagerequest; Página <suser> usuários = userRepository.findall (request); devolver usuários; }}A classe de controle adota a estrutura Springmvc, primeiro escreva um controle de base para implementar algumas funções gerais:
package org.muses.jeepatform.web.controller;import javax.servlet.http.HttpServletRequest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.servletRequestattributes; importar org.springframework.web.servlet.modelandView; public class Basecontroller {logger log = null; / *** Obtenha objeto de log* @return*/ public Logger getInstance () {if (log == null) {Log = LoggerFactory.getLogger (Basecontroller.class); } retornar log; } / *** Obtenha objeto de solicitação* / public httpServletRequest getRequest () {httpServletRequest request = ((servletRequestattributes) requestContextholder.getRequestAttributes ()). GetRequest (); solicitação de retorno; } / ** * Get ModelAndView * / public ModelAndView getModelandView () {return new ModelAndView (); }}Control Class Implementation:
pacote org.muses.jeepatform.web.controller; importar net.sf.json.jsonArray; importação net.sf.json.jsonObject; importar net.sf.json.jsonConfig; import org.apache.commons.collection.map.hashedMap; importação; org.muses.jeepatform.core.excelViewWrite; importar org.muses.jeepatform.core.javamailsender; importar org.muses.jeepatform.model.entity.user; org.muses.jeepatform.utils.DateUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.Sort;import org.springframework.steretype.Controller;import org.springframework.ui.model; importar org.springframework.web.bind.annotation.requestmapping; importar org.springframework.web.bind.annotation.requestparam; importação Org.sPringFramework.web.bind.antation.requestparam; importar; org.springframework.web.servlet.modlandView; importar javax.servlet.http.httpServletRequest; importar javax.servlet.http.httpSletResponse; import java.io.printwriter; importar 19*; */@Requestmapping ("/user")@classe de controlerpublic userController estende Basecontroller {@Autowired Userservice UserService; /** * Consulta todas as informações do administrador e exibi-las nas páginas * @param request * @param resposta * @param modelo * @return */@RequestMapping (value = "/Queryall", Produces = "Application/json; charSet = utf-8") @ResponseBody ModelAndLearlAll (hTTTTleTreTreQuest Solter PageIndexstr = request.getParameter ("PageIndex"); // Número de páginas por página int PAGESIZE = constantes.page_size; ModelAndView MV = this.getModElandView (); Página <suário> Página do usuário; if (PageIndexstr == null || "". Equals (PageIndexstr)) {PageIndexstr = "0"; } int PageIndex = Integer.ParseInt (PageIndexstr); userpage = userservice.findall (PageIndex+1, PageSize, Sort.direction.asc, "id"); mv.addObject ("totalCount", userpage.gettotalelements ()); mv.addObject ("PageIndex", PageIndex); // jsonConfig cfg = new jsonConfig (); // cfg.setexcludes (new String [] {"Handler", "HibernateLazyInitializer"}); JSONCONFIG JCG = novo JSONCONFIG (); JCG.RegisterJsonValueProcessor (DATE.Class, new DateJsonValueProcessor ("AA YYYY-MM-DD")); JsonArray jsonArray = jsonArray.FromObject (userPage.getContent (), JCG); //System.out.println (jsonArray.toString ()); mv.addObject ("Usuários", jsonArray.toString ()); mv.setViewName ("admin/user/sys_user_list"); retornar MV; }} 【Implementação da página front-end】
A implementação da visualização da página, consulte o jQuery.pagination.js (paginação js) e paginação.css (css em estilo de paginação).
Você pode baixá -lo aqui: //www.vevb.com/article/105013.htm
<%@ página contenttype = "text/html; charset = utf-8" pageEncoding = "utf-8"%> <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix = "ft "/jstl/core"%> <%@ taglib prefix = " uri = "http://java.sun.com/jsp/jstl/fmt"%> <% string path = request.getContextPath (); String basalepath = request.getscheme ()+": //"+request.getServername ()+":"+request.getServerport ()+caminho+"/";%> <! Doctype html> <html lang = "zh-cn"> <Cheft> <base href = "n%= bail charset = "utf-8"/> <meta http-equiv = "x-ua compatível com" content = "ie = edge"> <meta name = "viewport" content = "width = width device-width, scale inicial = 1"> <title> inserir título aqui </title> <!-bootstrap style-> <link = typey = " href = "<%= bashepath%> plugins/page/css/bootstrap-33.5.5.css" rel = "nofollow externo"/> <!-CSS necessário para jQuery.pagination-> <link type = "text/css" rel = "styleSeshet"/href = "<%= bastão = plug-insend/" css "=" StyleSheet "/href =" <%= bastion = " Nofollow "/> <script type =" text/javascript "src =" <%= bashepath%> plugins/page/js/jQuery.min.js "> </script> <!-js exigido por jQuery.pagination Note que deve ser colocado atrás de jQuery.js-> <script =" text/javr "" src = "<%= bashepath%> plugins/page/js/jquery.pagination.js"> </script> <script type = "text/javascript">/** para operações de paginação, use o jQuery.pagination plugin (nicky 20170729 Page **) // Quantidade de dados var totalCount = número ($ {totalCount}); $ (document) .ready (function () {// Ligação à paginação $ ("#paginação"). Paginação (TotalCount, {retorno de chamada: PageSelectCallback, prev_text: '<Página anterior', next_text: 'seguinte página>', itens_per_page: 6, num_display_etries: 6, current Page> ', itens_per_page: 6, num_display_entries: 6, Current Page>, "Usuário/Queryall? obj.email; "<td>"+nome de usuário+"</td>"+"<td>"+mark+"</td>"+"<td>"+telefone+"</td>"+"<td>"+email+"</td>"+"" ""+lastLogin+"</td>" "" <td> ""+") href = 'JavaScript: OpenEditDialog ("+id+"); // Este evento é PageSelectCallback (Index, JQ) {}/** Operação de paginação, usando o plug-in JQuery.Pagination Add por Nicky 20170729 END **/// Caixa de seleção All/Anti-Select var ischeckall = false; function docheck () {if (ischeckall) {$ ("input [type = 'checkbox']"). cada (function () {this.checked = false;}); ischeckall = false; } else {$ ("input [type = 'Caixa de seleção']"). cada (function () {this.checked = true;}); ischeckall = true; }} </script> </adhead> <body> <br> <div> <div> <div> <div> <form> <input type = "button" value = "enviar e -mail" onclick = "sendEmail ();" /> <input type = "button" value = "sendsms ();" /> <input type = "button" value = "exportexcel tabela" onclick = "exportExcel ();" /> <br> <br> <!-<input type = "text" id = "palavra-chave" placeholder = "por favor, digite a palavra-chave"> data de <input type = "text" placeholder = "por favor, digite a data de início" value = "$ {startDate}" id = "startDate" = "startDate" onclick = "wdatepicker}" , maxdate: '#f {$ dp. $ d (/' enddate/')}'}); "/> para <input type =" text "placeholder =" por favor, digite a data final "value =" $ {enddate} "id =" enddate "name =" enddate "onclick =" wdatepicker {datEft (e enddate "=" enddate "onCl =" "wddate}" , Mindate: '#f {$ dp. $ d (/' startDate/')}'}); " /> <input type = "button" value = "search" onclick = "dosesearch ();"/>-> </form> <tabela id = "mtable"> <thead> <tr> <th> <input type = "caixa de seleção" onclick = "docheck ();" /> </th> <th> Número de série </th> <th> Nome do usuário </th> <th> Descrição </th> <th> celular </th> <the> email </th> <th> login mais recente </th> <th> last Login ip </th> <th> operação </th> </tr> </wead> <tgin) </th> <h> operação </th> </tr> </head> <tbody) " <!-demonstração-> </div> </div> </div> </div> </div> </div> </div> </div> </body> </html> Exibição da página front-end:
OK, este blog é baseado em um projeto de código aberto do GitHub em desenvolvimento. O endereço do código do projeto é: https://github.com/u014427391/jeepatform
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.