[JAVA] Implémenter la fonction de pagination avec Spring Boot + Thymeleaf

Vous pouvez facilement implémenter la fonctionnalité de pagination d'écran avec Spring Boot + Thymeleaf. Image d'écran une fois terminé スクリーンショット 2017-01-21 23.25.18.png

Environnement de vérification

la mise en oeuvre

Le premier est la couche de domaine.

@Entity
@Table(name="word_info")
public class Word implements Serializable {

	private static final long serialVersionUID = -870708489937857961L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.TABLE, generator="seqTable")
	@TableGenerator(name="seqTable", table="seq_table", pkColumnName="seq_name", pkColumnValue="word_seq", valueColumnName="seq_value")
	@Column(name="id")
	private Long id;
	
	@Column(name="word")
	private String word;
	
	@Column(name="meaning")
	private String meaning;
	
	@Column(name="example")
	private String example;

	//get / set omis
	...
}

Définissez une classe de référentiel JPA pour obtenir la liste. Utilisez la classe Page au lieu de List.

@Repository
public interface WordRepository extends CrudRepository<Word, Long>{
	
	public Page<Word> findAll(Pageable pageable);

}

Vient ensuite la couche Service.

@Service
public class WordService {
	
	@Autowired
	private WordRepository wordRepo;
	
	public Page<Word> getAllWord(Pageable pageable) {

		return wordRepo.findAll(pageable);
	}

}

Couche de présentation.

@Controller
public class MainController {
	
	@Autowired
	private WordService wordService;
	
	@RequestMapping(value="/word/wordList", method=RequestMethod.GET)
	public String getWordList(Model model, Pageable pageable) {
		Page<Word> wordsPage = wordService.getAllWord(pageable);
		model.addAttribute("page", wordsPage);
		model.addAttribute("words", wordsPage.getContent());
		model.addAttribute("url", "/word/wordList");
		
		return "/word/wordList";
	}
}

Réglage du nombre d'éléments à afficher

Définissez le nombre maximum d'éléments à afficher pour chaque page.

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

  @Override
  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
      PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
      //Nombre d'éléments à afficher par page
      resolver.setFallbackPageable(new PageRequest(0, 5));
      argumentResolvers.add(resolver);
      super.addArgumentResolvers(argumentResolvers);
  }

}

Enfin, l'implémentation côté Thymeleaf.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	  xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="UTF-8" />
		<link th:substituteby="common/header :: common_header"/>
		<title>Word List</title>
	</head>
	<body>
		<table border="1">
			<tr>
				<th>ID</th>
				<th>WORD</th>
				<th>MEANING</th>
				<th>EXAMPLE</th>
			</tr>
			<tr th:each="word:${words}">
				<td th:text="${word.id}"></td>
				<td th:text="${word.word}"></td>
				<td th:text="${word.meaning}"></td>
				<td th:text="${word.example}"></td>
			</tr>
		</table>
		
		<div th:fragment='paginationbar'>
			<ul>
				<li th:class="${page.first} ? 'disabled':''" style="display:inline">
					<span th:if="${page.first}">← Premier</span>
					<a th:if="${not page.first}" th:href="@{${url}(page=0)}">← Premier</a>
				</li>
				<li th:each='i : ${#numbers.sequence(0, page.totalPages-1)}' th:class="(${i}==${page.number})? 'active' : ''" style="display:inline">
                	<span th:if='${i}==${page.number}' th:text='${i+1}'>1</span>
               	 	<a th:if='${i}!=${page.number}' th:href="@{${url}(page=${i})}">
               	 		<span th:text='${i+1}'>1</span>
               	 	</a>
                </li>
				<li th:class="${page.last} ? 'disabled':''" style="display:inline">
					<span th:if="${page.last}">Fin ➝</span>
					<a th:if="${not page.last}" th:href="@{${url}(page=(${page.totalPages}-1))}">Fin ➝</a>
				</li>
			</ul>
		</div>
	</body>
</html>

Personnaliser

Dans le cas d'un grand nombre de pages comme indiqué ci-dessous, si vous souhaitez afficher uniquement certains numéros de page, vous pouvez créer une classe wrapper pour Page et la personnaliser. 2017-12-08_092643.jpg

Implémentation de la classe wrapper

public class PageWrapper<T> {
    public static final int MAX_PAGE_ITEM_DISPLAY = 5;
    private Page<T> page;
    private List<PageItem> items;
    private int currentNumber;
    private String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public PageWrapper(Page<T> page, String url){
        this.page = page;
        this.url = url;
        items = new ArrayList<PageItem>();

        currentNumber = page.getNumber() + 1;

        int start, size;
        if (page.getTotalPages() <= MAX_PAGE_ITEM_DISPLAY){
            start = 1;
            size = page.getTotalPages();
        } else {
            if (currentNumber <= MAX_PAGE_ITEM_DISPLAY - MAX_PAGE_ITEM_DISPLAY/2){
                start = 1;
                size = MAX_PAGE_ITEM_DISPLAY;
            } else if (currentNumber >= page.getTotalPages() - MAX_PAGE_ITEM_DISPLAY/2){
                start = page.getTotalPages() - MAX_PAGE_ITEM_DISPLAY + 1;
                size = MAX_PAGE_ITEM_DISPLAY;
            } else {
                start = currentNumber - MAX_PAGE_ITEM_DISPLAY/2;
                size = MAX_PAGE_ITEM_DISPLAY;
            }
        }

        for (int i = 0; i<size; i++){
            items.add(new PageItem(start+i, (start+i)==currentNumber));
        }
    }

    public List<PageItem> getItems(){
        return items;
    }

    public int getNumber(){
        return currentNumber;
    }

    public List<T> getContent(){
        return page.getContent();
    }

    public int getSize(){
        return page.getSize();
    }

    public int getTotalPages(){
        return page.getTotalPages();
    }

    public boolean isFirstPage(){
        return page.isFirst();
    }

    public boolean isLastPage(){
        return page.isLast();
    }

    public boolean isHasPreviousPage(){
        return page.hasPrevious();
    }

    public boolean isHasNextPage(){
        return page.hasNext();
    }

    public class PageItem {
        private int number;
        private boolean current;
        public PageItem(int number, boolean current){
            this.number = number;
            this.current = current;
        }

        public int getNumber(){
            return this.number;
        }

        public boolean isCurrent(){
            return this.current;
        }
    }
}

Contrôle du changement de classe

Utilisez une classe wrapper au lieu de Page.

@Controller
public class MainController {
	
	@Autowired
	private WordService wordService;

	@RequestMapping("/word/register")
	public String wordRegister(WordForm wordForm) {
		wordService.addWord(wordForm);
		return "/word/wordRegister";
	}
	
	@RequestMapping(value="/word/wordList", method=RequestMethod.GET)
	public String getWordList(Model model, Pageable pageable) {
		Page<Word> wordPage = wordService.getAllWord(pageable);
		PageWrapper<Word> page = new PageWrapper<Word>(wordPage, "/word/wordList");
		model.addAttribute("page", page);
		model.addAttribute("words", page.getContent());
		
		return "/word/wordList";
	}
}

Thymeleaf

Modifiez la partie de pagination comme suit.

	...

		<div th:fragment='paginationbar'>
			<ul class='pagination pagination-centered'>
				<li th:class="${page.firstPage}?'disabled':''" style="display:inline">
					<span th:if='${page.firstPage}'>← Premier</span>
					<a th:if='${not page.firstPage}' th:href='@{${page.url}(page=0,size=${page.size})}'>← Premier</a>
				</li>
				<li th:class="${page.hasPreviousPage}? '' : 'disabled'" style="display:inline">
					<span th:if='${not page.hasPreviousPage}'>«</span>
					<a th:if='${page.hasPreviousPage}' th:href='@{${page.url}(page=${page.number-2},size=${page.size})}'>«</a>
				</li>
	                
	                
				<li th:each='item : ${page.items}' th:class="${item.current}? 'active' : ''" style="display:inline">
					<span th:if='${item.current}' th:text='${item.number}'>1</span>
					<a th:if='${not item.current}' th:href='@{${page.url}(page=${item.number-1},size=${page.size})}'>
					<span th:text='${item.number}'>1</span>
					</a>
				</li>
				<li th:class="${page.hasNextPage}? '' : 'disabled'" style="display:inline">
					<span th:if='${not page.hasNextPage}'>»</span>
					<a th:if='${page.hasNextPage}' th:href='@{${page.url}(page=${page.number},size=${page.size})}'>»</a>
				</li>
				<li th:class="${page.lastPage}? 'disabled' : ''" style="display:inline">
					<span th:if='${page.lastPage}'>Fin ➝</span>
					<a th:if='${not page.lastPage}' th:href='@{${page.url}(page=${page.totalPages - 1},size=${page.size})}'>Fin ➝</a>
				</li>
			</ul>
		</div>
	...

Référence: https://github.com/mtiger2k/pageableSpringBootDataJPA

Recommended Posts

Implémenter la fonction de pagination avec Spring Boot + Thymeleaf
Implémenter CRUD avec Spring Boot + Thymeleaf + MySQL
Implémenter GraphQL avec Spring Boot
Essayez d'implémenter la fonction de connexion avec Spring Boot
Exécutez l'application WEB avec Spring Boot + Thymeleaf
Télécharger avec Spring Boot
Créez une application CRUD avec Spring Boot 2 + Thymeleaf + MyBatis
Créez votre propre utilitaire avec Thymeleaf avec Spring Boot
[Introduction à Spring Boot] Fonction d'authentification avec Spring Security
Générer un code à barres avec Spring Boot
Hello World avec Spring Boot
Démarrez avec Spring Boot
Bonjour tout le monde avec Spring Boot!
Exécutez LIFF avec Spring Boot
Connexion SNS avec Spring Boot
Implémentez une API Rest simple avec Spring Security avec Spring Boot 2.0
[Java] Thymeleaf Basic (Spring Boot)
Téléchargement de fichiers avec Spring Boot
Spring Boot commençant par copie
Fonction de connexion avec Spring Security
Spring Boot à partir de Docker
Hello World avec Spring Boot
Définir des cookies avec Spring Boot
[Spring Boot] Recette de processus de pagination facile
Utiliser Spring JDBC avec Spring Boot
Ajouter un module avec Spring Boot
Premiers pas avec Spring Boot
Créer un micro service avec Spring Boot
Envoyer du courrier avec Spring Boot
Gérez l'API de date et d'heure Java 8 avec Thymeleaf avec Spring Boot
Implémenter l'API REST avec Spring Boot et JPA (Application Layer)
Implémenter l'API REST avec Spring Boot et JPA (couche d'infrastructure)
Jusqu'à INSERT et SELECT sur Postgres avec botte de printemps et feuille de thym
Utilisez thymeleaf3 avec le parent sans spécifier spring-boot-starter-parent dans Spring Boot
Implémenter l'API REST avec Spring Boot et JPA (Domain Layer Edition)
Implémentez une API Rest simple avec Spring Security & JWT avec Spring Boot 2.0
Utiliser l'authentification de base avec Spring Boot
Mise en œuvre de la fonction d'authentification avec Spring Security ②
Implémenter le lien texte avec Springboot + Thymeleaf
gRPC sur Spring Boot avec grpc-spring-boot-starter
Implémentez la fonction d'authentification avec Spring Security ③
Créez une application avec Spring Boot 2
Déploiement à chaud avec le développement Spring Boot
Liaison de base de données avec doma2 (Spring boot)
Programmation Spring Boot avec VS Code
Jusqu'à "Hello World" avec Spring Boot
Créer une application d'enquête avec Spring Boot
Mise en œuvre de la fonction d'authentification avec Spring Security ①
Obtenez des résultats de validation avec Spring Boot
Implémenter le téléchargement de fichiers avec Spring MVC
(Intellij) Hello World avec Spring Boot
Créez une application avec Spring Boot
Implémenter l'API REST avec Spring Boot
Fonction de profil Spring et application Spring Boot.
Google Cloud Platform avec Spring Boot 2.0.0
J'ai essayé GraphQL avec Spring Boot
[Java] Intégration LINE avec Spring Boot
À partir de Spring Boot 0. Utilisez Spring CLI
J'ai essayé Flyway avec Spring Boot