SpringData Pageable + Thymeleafを使用してページネーションを実装

#目的
・一覧画面にいい感じにページングしたい
・実装はなるべく簡単な方がいい

#環境
SpringBoot 2.1.0.RELEASE
Spring Data Commons 2.1.2.RELEASE
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Pageable.html

#実装
###Configuration
```java

import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyAppWebConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(
            List<HandlerMethodArgumentResolver> argumentResolvers) {
        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
        // 1ページに表示する最大件数を10件に
        resolver.setMaxPageSize(10);
        argumentResolvers.add(resolver);
    }
}
```

###Repository
JPAを使用しました。

```java

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MyHistoryRepository
        extends PagingAndSortingRepository<MyHistory, Long> {

    Page<MyHistory> findByUserIdAndDeletedFalse(
            String userId, Pageable pageable);

}
```

###Service
```java

@Service
@Transactional(readOnly = true)
public class MyHistoryServiceImpl implements MyHistoryService {

    @Autowired
    MyHistoryRepository myHistoryRepository;

    public Page<MyHistoryModel> getMyHistoryByUserId(
            String userId, Pageable pageable) {
        // 取得したentityをmodelに変換して返却
        return myHistoryRepository
                .findByUserIdAndDeletedFalse(userId,
                        pageable)
                .map(MyHistoryConverter::entityToModel);
    }
}
```

###Controller
```java

@Controller
@RequestMapping("/mypage")
public class MypageController {

    @Autowired
    MyHistoryService myHistoryService;

    @GetMapping
    public String doGetMypage(@AuthenticationPrincipal MyUserDetails user,
            Model model, Pageable pageable) {
        model.addAttribute("myHistory", myHistoryService
                .getMyHistoryByUserId(user.getUserId(), pageable));
        return "view";
    }
}
```

###View(Thymeleaf)
```html
<!-- ページャーのところだけです -->
<div th:unless="${myHistory.getContent().size()==0}" th:fragment='paginationbar'>
		<ul>
			<li th:class="${myHistory.first} ? 'disabled':''" style="display:inline">
				<span th:if="${myHistory.first}">first</span>
				<a th:if="${not myHistory.first}" th:href="@{${'/mypage'}(page=0)}">first</a>
			</li>
			<li th:each='i : ${#numbers.sequence(0, myHistory.totalPages-1)}' th:class="(${i}==${myHistory.number})? 'active' : ''" style="display:inline">
		<span th:if='${i}==${myHistory.number}' th:text='${i+1}'>1</span>
			<a th:if='${i}!=${myHistory.number}' th:href="@{${'/mypage'}(page=${i})}">
				<span th:text='${i+1}'>1</span>
			</a>
		</li>
		<li th:class="${myHistory.last} ? 'disabled':''" style="display:inline">
			<span th:if="${myHistory.last}">last</span>
			<a th:if="${not myHistory.last}" th:href="@{${'/mypage'}(page=(${myHistory.totalPages}-1))}">last</a>
		</li>
	</ul>
</div>
```

#感想
Pageableを渡すことで簡単にページネーションが実装できました。
今回は取得したentityそのものをページネーションの対象としました。
今回の実装にあたり、取得したentityの１フィールドについてページネーションできれば、
殆ど既存のソースコードに変更を加えずに対応できたのですが、調べた限りそれは無理のようでした。