Initial SpringBoot, development community home page

Posted by beedie on Fri, 19 Nov 2021 17:54:36 +0100

1.1 Course Introduction

Course objectives:

  The premise of in-depth understanding of the framework is to apply it. Flexible.

Project introduction: discussion function of Niuke network and discussion community.

Java Web focuses on the server side, not the front-end page. The front end is familiar with Html common tags, CSS and JS

Home page: post list, post, sensitive word filtering --- focus, algorithm

Log in, view the post content, reply, permission control, and comment on other people's replies

  Login, email, connection, verification code, account and password judgment, log in to view the personal home page, view the attention, be concerned, post once, click the attention.

Focus on performance issues, how not to let the server hang up!!!

Private letter, reply to private letter

Message notification, message queue redis, multithreading concurrency, consumer producer mode.

Full site search, professional search engine, high performance, keyword highlighting. How to Chinese word segmentation, highlight, and how search engines and databases synchronize data.

Administrator usage: website UV, number of active users.

How to improve performance and security.

Technical architecture:

JavaEE

Spring is already an industry standard for real-time, including multiple frameworks.

Spring, SpringBoot Web application framework

Spring MVC -- how to handle browser requests

MyBatis -- how to access database information, integrate with spring and SSM framework -- realize the basic functions of the project, register, log in, post, comment and private letters all the time. General functions.

Redis -- data exists in memory, high performance

Kafka -- message queue, publishing messages

Elasticsearch -- search engine

Integrate with Spring to improve performance

Spring Security -- improving system security

Spring Actuator -- monitors the online system and allows the operation and maintenance personnel to monitor the system status at any time

 

Build project: create, compile, test, package and generate documents for the project, Maven

Version control server: backup, version control, team member server

1.2 build development environment

  Install Maven to create a compilation and packaging management jar package

~Home directory - system disk m2

Central warehouse: Maven warehouse, image -- third party copy of maven, Alibaba cloud, private server warehouse

Download Maven

Change to alicloud image

Configure environment variables and install maven, cmd or IDEA

Spring Initializr: integrates commonly used packages and can be imported in batches

  Configure the basic information of the project, import the jar s required by the project, search function, batch import, and create a Java Web project

Spring Boot has a TomCat server in its package

  What we search for is start dependence

Start dependency is a combination of a group of packages. A small number of dependencies import a large number of packages

Almost no configuration

Endpoint control -- after online

server.port=8080 / / configure Tomcat server port
 Server. Servlet. Context path = / community / / project access path

1.3 getting started with spring

Spring family bucket

Spring Framewprk: basic core --- spring---spring.io

Spring Boot: it is more convenient to build projects

Spring Cloud: Micro service, split into several subprojects

Spring Cloud Data Flow:Spring does data integration. Many customer service terminals (mobile phones, watches, smart wear...) collect data and how to integrate.

  An idea of IoC/AOP management object, Bean in Spring

Ioc: dependency injection, object-oriented management idea

Aop: facing section

Spring documentation

https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/

  Control inversion: the traditional way is to create an object A, create an object B, call B in A, and coupling between AB, which is not conducive to later maintenance, and achieve coupling degree between bean by control inversion. Through dependency injection -- Based on Ioc container -- a bean factory

The IOC container helps us manage beans. We need to know what beans are and bean configuration information, and understand the relationship between beans through bean configuration.

In Spring boot, starting a web project not only helps us start a TomCat, but also helps us create a Spring container. After the container is created, some bean s under some packages will be automatically scanned and assembled

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration//Auto configuration
@ComponentScan(//Automatic component scanning
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
What will be scanned:
@ComponentScan -- automatic component scanning, which will automatically scan the bean s under the package and sub package of the configuration class
 There should also be @ Controller annotation on the bean
 Therefore, adding service / Component / repository / controller to bean s is implemented by components

Service -- owner component

Componen t -- all common

Repository -- a component of database access

Controller -- primary request

 

@Service
public class AlphaService {
    public AlphaService() {
        System.out.print("Constructor instantiation");
    }

    @PostConstruct//This method will be called after the constructor.
    public void init(){
        System.out.print("initialization");
    }
    @PreDestroy//Call before object destruction
    public void destory(){
        System.out.print("destory");
    }
}

  The bean is instantiated only once. It is a singleton mode,

Annotate whether the bean is an object or multiple objects by adding @ Scpoe("singleton", "prototype")

"Singleton" -- the default is a singleton

"prototype" -- a new bean will be created for each access

Assembling third-party classes with configuration classes

@Configuration
public class AlphaConfig {
    @Bean
    public SimpleDateFormat simpleDateFormat(){
        //The returned object is transferred to the IOC container
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }
}

  Get bean s by dependency injection

No getBean()

Write an attribute, inject the attribute through annotation, and specify the specific implementation class through annotation

IoC means control inversion, which is an object-oriented programming idea. Spring implements the idea of IoC by means of dependency injection.
Spring   Functions of the Framework: Transactions / Scheduling/Security
@Autowired is used to inject beans, @ Qualifier is used to declare the name of beans, @ beans is used to assemble third-party beans,
@Configuration is used to declare configuration classes.

1.4SpringMVC introduction

Http:

Hyper Text Transfer Protocol

The application layer protocol used to transmit Html and other content. The bottom layer is TCP

Specifies how browsers and services communicate and the data format for communication

https://www.ieft.org

https://developer.mozilla.org/zh-CN/      Firefox browser -- support Chinese

HTTP stream

When the client wants to interact with the server (the server refers to the final server or an intermediate agent), the process is as follows:

  1. Open a TCP connection: a TCP connection is used to send one or more requests and receive response messages. The client may open a new connection, reuse an existing connection, or open several new TCP connections to the server.
  2. Send an HTTP message: the HTTP message (before HTTP/2) is semantically readable. In HTTP/2, these simple messages are encapsulated in frames, which makes the messages can not be read directly, but the principle is still the same.
    GET / HTTP/1.1
    Host: developer.mozilla.org
    Accept-Language: fr
  3. Read the message information returned by the server:
    HTTP/1.1 200 OK
    Date: Sat, 09 Oct 2010 14:28:02 GMT
    Server: Apache
    Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
    ETag: "51142bc1-7449-479b075b2891b"
    Accept-Ranges: bytes
    Content-Length: 29769
    Content-Type: text/html
    
    <!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
  4. Close the connection or reuse the connection for subsequent requests.

When the HTTP pipeline starts, subsequent requests can be sent without waiting for the successful response of the first request. However, HTTP pipelining has proved difficult to implement in the existing network, because there are many old software and modern software coexisting in the existing network. Therefore, the HTTP pipeline has been replaced by HTTP/2 frames that behave more robustly with multiple requests.

The request consists of the following elements:

  • An HTTP method , often by a verb like GETPOST Or a noun like OPTIONSHEAD To define the action behavior of the client. Usually, the operation of the client is to obtain resources (GET method) or send HTML form Form value (POST method), although there are other operations in some cases.
  • The path of the resource to be obtained is usually the URL of the element resource that is obvious in the context. It does not protocol (http://),domain (developer.mozilla.org), or TCP port (en-US) (HTTP is usually on port 80).
  • HTTP protocol version number.
  • An optional header for the server to express other information headers.
  • For some methods such as POST, the body of the message contains the transmitted resources, which is similar to the body of the response message.

The response message contains the following elements:

  • HTTP protocol version number.
  • A status code( status code )To inform the successful or failed execution of the corresponding request and the reason for the failure.
  • A status information, which is non authoritative status code description information and can be set by the server itself.
  • HTTP headers , similar to the request header.
  • Optional. Compared with the request message, the response message usually contains the acquired resource body.

 

The server responds to the request and returns an HTML file. The client parses the HTML and finds that the server resources such as pictures, CSS and JS need to be referenced, so it requests the server to get the returned CSS, JS, pictures and other resources.

MVC three-tier architecture

The three-tier architecture of the server: the browser accesses the data, first accesses the presentation layer, obtains the data from the presentation layer, the presentation layer will call the business layer to process the business, and the business layer calls the data layer to access the database data.

MVC design pattern, which has no corresponding relationship with the three-tier architecture, mainly solves the problem of the presentation layer

MVC is called by DispatcherServlet:

  Old version

  The request is uniformly processed by the front controller dispatcher servlet. It will find the controller according to the path provided by the mapping annotation, and the controller will encapsulate the data into the model and return to the front controller; After getting the data, the controller will try to replace some variables in the view template with the values in the model to generate a dynamic web page

Template engine: dynamically generate HTML pages according to model data

  html file everyone can understand.

Standard expression; Those that need to be replaced

Judge the pre circulation: whether the model data is null, do different processing according to different data, and cycle the data such as collection and array

Template layout: reuse the same area.

  Do not enable the template cache during development. If there is a cache, you can enable the cache after online, which will reduce the pressure on the server.

Configuration is to inject values into a Bean.

spring boot documentation:

https://docs.spring.io/spring-boot/docs/2.1.10.RELEASE/reference/htmlsingle/

Spring Boot Reference Guide

View common configurations:

 Spring Boot Reference Guide

# THYMELEAF (ThymeleafAutoConfiguration)
spring.thymeleaf.cache=true # Whether to enable template caching.
spring.thymeleaf.check-template=true # Whether to check that the template exists before rendering it.
spring.thymeleaf.check-template-location=true # Whether to check that the templates location exists.
spring.thymeleaf.enabled=true # Whether to enable Thymeleaf view resolution for Web frameworks.
spring.thymeleaf.enable-spring-el-compiler=false # Enable the SpringEL compiler in SpringEL expressions.
spring.thymeleaf.encoding=UTF-8 # Template files encoding.
spring.thymeleaf.excluded-view-names= # Comma-separated list of view names (patterns allowed) that should be excluded from resolution.
spring.thymeleaf.mode=HTML # Template mode to be applied to templates. See also Thymeleaf's TemplateMode enum.
spring.thymeleaf.prefix=classpath:/templates/ # Prefix that gets prepended to view names when building a URL.
spring.thymeleaf.reactive.chunked-mode-view-names= # Comma-separated list of view names (patterns allowed) that should be the only ones executed in CHUNKED mode when a max chunk size is set.
spring.thymeleaf.reactive.full-mode-view-names= # Comma-separated list of view names (patterns allowed) that should be executed in FULL mode even if a max chunk size is set.
spring.thymeleaf.reactive.max-chunk-size=0B # Maximum size of data buffers used for writing to the response.
spring.thymeleaf.reactive.media-types= # Media types supported by the view technology.
spring.thymeleaf.render-hidden-markers-before-checkboxes=false # Whether hidden form inputs acting as markers for checkboxes should be rendered before the checkbox element itself.
spring.thymeleaf.servlet.content-type=text/html # Content-Type value written to HTTP responses.
spring.thymeleaf.servlet.produce-partial-output-while-processing=true # Whether Thymeleaf should start writing partial output as soon as possible or buffer until template processing is finished.
spring.thymeleaf.suffix=.html # Suffix that gets appended to view names when building a URL.
spring.thymeleaf.template-resolver-order= # Order of the template resolver in the chain.
spring.thymeleaf.view-names= # Comma-separated list of view names (patterns allowed) that can be resolved.

  View encapsulated request and response information

 @RequestMapping(" /http ")
    public void http(HttpServletRequest request, HttpServletResponse response){
        //Get request data
        System.out.println(request.getMethod());
        System.out.println(request.getServletPath());
        Enumeration<String> enumeration = request.getHeaderNames();
        while(enumeration.hasMoreElements()){
            String name = enumeration.nextElement();
            String value = request.getHeader(name);
            System.out.println(name+":"+value);
        }
    }

  There are several ways to process requests and responses in spring MVC:

GET

POST

How to respond to HTML --- model & View

Response JSON data (asynchronous request)

@Autowired
    private AlphaService alphaService;

    @RequestMapping("/hello")
    @ResponseBody
    public String sayHello() {
        return "Hello Spring Boot.";
    }

    @RequestMapping("/data")
    @ResponseBody
    public String getData() {
        return alphaService.find();
    }

    @RequestMapping("/http")
    public void http(HttpServletRequest request, HttpServletResponse response) {
        // Get request data
        System.out.println(request.getMethod());
        System.out.println(request.getServletPath());
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String name = enumeration.nextElement();
            String value = request.getHeader(name);
            System.out.println(name + ": " + value);
        }
        System.out.println(request.getParameter("code"));

        // Return response data
        response.setContentType("text/html;charset=utf-8");
        try (
                PrintWriter writer = response.getWriter();
        ) {
            writer.write("<h1>Niuke network</h1>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // GET request

    // /students?current=1&limit=20
    @RequestMapping(path = "/students", method = RequestMethod.GET)
    @ResponseBody
    public String getStudents(
            @RequestParam(name = "current", required = false, defaultValue = "1") int current,
            @RequestParam(name = "limit", required = false, defaultValue = "10") int limit) {
        System.out.println(current);
        System.out.println(limit);
        return "some students";
    }

    // /student/123
    @RequestMapping(path = "/student/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String getStudent(@PathVariable("id") int id) {
        System.out.println(id);
        return "a student";
    }

    // POST request
    @RequestMapping(path = "/student", method = RequestMethod.POST)
    @ResponseBody
    public String saveStudent(String name, int age) {
        System.out.println(name);
        System.out.println(age);
        return "success";
    }

// Response HTML data
    @RequestMapping(path = "/teacher", method = RequestMethod.GET)
    public ModelAndView getTeacher() {
        //The model layer is packed to facilitate the fumigation of the template
        ModelAndView mav = new ModelAndView();//Create modelAndView objects to encapsulate data and view display
        mav.addObject("name", "Zhang San");//Encapsulate data
        mav.addObject("age", 30);
        mav.setViewName("/demo/view");//Fumigation view template
        return mav;
    }
 //Another simple model
    @RequestMapping(path = "/school", method = RequestMethod.GET)
    public String getSchool(Model model) {//When DispatcherServlet calls this method and needs a model for analysis, it instantiates the object and passes parameters
        //Dispatcher servlet holds model data and view views, and can also be implemented
        model.addAttribute("name", "Peking University");
        model.addAttribute("age", 80);
        return "/demo/view";
    }

// Response JSON data (asynchronous request)
    // Register and enter the user name. When the cursor leaves the text box and loses focus, it will connect to the database to judge whether the user name is occupied and return true/false, but the page has not been refreshed
    //The current web page does not refresh, but accesses a server and returns data - asynchronous request
    // Java object - > json string - > JS object can realize cross language information transmission with json

    @RequestMapping(path = "/emp", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> getEmp() {
        Map<String, Object> emp = new HashMap<>();
        emp.put("name", "Zhang San");
        emp.put("age", 23);
        emp.put("salary", 8000.00);
        return emp;
    }

    @RequestMapping(path = "/emps", method = RequestMethod.GET)
    @ResponseBody
    public List<Map<String, Object>> getEmps() {
        List<Map<String, Object>> list = new ArrayList<>();
        //Control and circulation
        Map<String, Object> emp = new HashMap<>();
        emp.put("name", "Zhang San");
        emp.put("age", 23);
        emp.put("salary", 8000.00);
        list.add(emp);
        emp = new HashMap<>();
        emp.put("name", "Li Si");
        emp.put("age", 24);
        emp.put("salary", 9000.00);
        list.add(emp);
        emp = new HashMap<>();
        emp.put("name", "Wang Wu");
        emp.put("age", 25);
        emp.put("salary", 10000.00);
        list.add(emp);
        return list;
    }

 

HTTP protocol specifies the four steps of communication between browser and server, which are: establishing connection, sending request, receiving response and closing connection
HTTP request message includes request method, request path, protocol version, message header, etc
The HTTP response message includes status code, status name, protocol version, message header, etc
Spring MVC is applied to the presentation layer, which reduces the coupling degree of the presentation layer code
The core component of Spring MVC is DispatcherServlet, which is responsible for distributing all requests
Thymeleaf advocates natural templates, that is, HTML files are used as templates
The syntax supported by Thymeleaf includes: standard expression, judgment and loop, template layout, etc
The premise for Thymeleaf to generate dynamic HTML is that you should provide template files and dynamic data for it
@RequestMapping can declare the access path of a class or method, as well as the method of the request
@PathVariable can bind the parameters in the request path to the parameters of the method in the controller
@RequestParam can bind the parameters in the request object to the parameters of the method in the controller
@ResponseBody is used to respond to the browser string synchronously and asynchronously
In the controller method, we can directly use Request and Response objects to process requests and responses
ModelAndView object, which can store both model data and template path

1.5 MyBatis

MySQL installation and configuration - detailed tutorial - Winton-H - blog Park

to configure:

Change time zone

 MyBatis

In spring boot, the first three (SqlSessionFactory/SqlSession/XML configuration file) are integrated

 Introduction to mybatis – MyBatis 3

mybatis-spring –     spring integrates Mybatis

The password is encrypted. salt is a random string. In order to prevent the user's password from being cracked too simply, a five digit random string is spliced behind the user's password, and then encrypted

1.6 development community home page

Development process: the web browser solves the requests and responses between the browser and the server. Any function can be divided into several requests and responses

Execution process of a request: Dao -- > Service -- > controller first

  Distributed implementation:

Develop the community home page and display the first ten posts.

Develop paging components to display all posts in paging.

Comment form

Step 1: develop data access layer dao, involving entity class, dao interface and mapper.xml to configure SQL

  entit ---- write table entity class

dao --- interface class -- use @ mapper annotation to write mapper configuration file corresponding to dao interface and configure SQL statement corresponding to interface method

Step 2: develop Service layer and business layer

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public User findUserById(int id){
        return userMapper.selectById(id);
    }
    public User findUserByName(String username){
        return userMapper.selectByName(username);
    }
    public User findUserByEmail(String email){
        return userMapper.selectByEmail(email);
    }
}

Is to use the dao layer mapper interface method.

Part III: view layer

Dynamic template page, parameter replacement.

<!--map.get("user")->user.getHeaderUrl()  -->
<img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="User Avatar" style="width:50px;height:50px;">
<!--map.get("user")->user.getHeaderUrl()  -->
							<img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="User Avatar" style="width:50px;height:50px;">

<ul class="list-unstyled">                                                                                                                                                           
	<!-- loop each ,Traverse to one in the collection at a time map-->                                                                                                                                                  
	<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">                                                                                                    
		<a href="site/profile.html">                                                                                                                                                 
			<!--dynamic data -->                                                                                                                                                              
			<!--map.get("user")->user.getHeaderUrl()  -->                                                                                                                            
			<!--/*@thymesVar id="user" type=""*/-->                                                                                                                                  
			<img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="User Avatar" style="width:50px;height:50px;">                                                              
		</a>                                                                                                                                                                         
		<div class="media-body">                                                                                                                                                     
			<h6 class="mt-0 mb-3">                                                                                                                                                   
				<!--utext   Can handle escape characters-->                                                                                                                                              
				<!--/*@thymesVar id="post" type=""*/-->                                                                                                                              
				<a href="#"Th: utext =" ${map. Post. Title} "> prepare for the spring recruit, brush the questions in the interview and review with him. It's all done in a month</a>                                                                                                   
				<!--Decide the top or essence according to the type and status of the post.-->                                                                                                                                             
				<span class="badge badge-secondary bg-primary" th:if="${map.post.type==1}">Topping</span>                                                                                 
				<span class="badge badge-secondary bg-danger" th:if="${map.post.status==1}">Essence</span>                                                                                
			</h6>                                                                                                                                                                    
			<div class="text-muted font-size-12">                                                                                                                                    
				<!--Author and release time of the post-format-->                                                                                                                                                
				<u class="mr-3" th:utext="${map.user.username}">Han jiangxue</u> Published in <b th:text="${#dates.format(map.post.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</b>         
				<ul class="d-inline float-right">                                                                                                                                    
					<li class="d-inline ml-2">Like 11</li>                                                                                                                              
					<li class="d-inline ml-2">|</li>                                                                                                                                 
					<li class="d-inline ml-2">Reply 7</li>                                                                                                                              
				</ul>                                                                                                                                                                
			</div>                                                                                                                                                                   
		</div>						                                                                                                                                                 
	</li>                                                                                                                                                                            
</ul>                                                                                                                                                                                
<!-- paging -->                                                                                                                                                                          
<!-- paging -->                                                                                                                              
<nav class="mt-5" th:if="${page.rows>0}">                                                                                                
	<ul class="pagination justify-content-center">                                                                                       
		<li class="page-item">                                                                                                           
			<a class="page-link" th:href="@{${page.path}(current=1)}">home page</a>                                                             
		</li>                                                                                                                            
		<li th:class="|page-item ${page.current==1?'disabled':''}|">                                                                     
			<a class="page-link" th:href="@{${page.path}(current=${page.current-1})}">previous page</a></li>                                       
		<li th:class="|page-item ${i==page.current?'active':''}|" th:each="i:${#numbers.sequence(page.from,page.to)}">                   
			<a class="page-link" href="#" th:text="${i}">1</a>                                                                           
		</li>                                                                                                                            
		<li th:class="|page-item ${page.current==page.total?'disabled':''}|">                                                            
			<a class="page-link" th:href="@{${page.path}(current=${page.current+1})}">next page</a>                                            
		</li>                                                                                                                            
		<li class="page-item">                                                                                                           
			<a class="page-link" th:href="@{${page.path}(current=${page.total})}">Last </a>                                                 
		</li>                                                                                                                            
	</ul>                                                                                                                                
</nav>                                                                                                                                   

  This must be noted, or an error will be reported:

<!--	<build>-->
<!--		<plugins>-->
<!--			<plugin>-->
<!--				<groupId>org.springframework.boot</groupId>-->
<!--				<artifactId>spring-boot-maven-plugin</artifactId>-->
<!--				<version>2.4.5</version>-->
<!--			</plugin>-->
<!--		</plugins>-->
<!--	</build>-->

  Further development of paging function:

Subpackage paging component Page

Get the corresponding page data according to the clicked page number, display and return the current page number, page data and the total number of pages of data.

//Information related to sub packaging and paging

    //Current page number
    private int current = 1;
    //Display upper limit
    private int limit = 10;
    //Total data (calculated total pages)
    private int rows;
    //Query path (multiplex paging connection)
    private String path;

//    Gets the starting line of the front page of the party flag
    public int getOffset(){
        return (current-1)*limit;//Database from row 0
    }
//    Get total pages
    public int getTotal(){
        if(rows%limit==0){
            return rows/limit;
        }else{
            return rows/limit+1;
        }
    }
//    Get start page number
    public int getFrom(){
        int from = current-2;
        return from<1 ? 1:from;//Not less than 1
    }

//    Get end page number
    public int getTo(){
        int to = current+2;
        int total = getTotal();
        return to>total ? total:to;
    }
// Method, spring MVC will automatically instantiate the Model and Page, and inject the Page into the Model
        // Therefore, the data in the Page object can be accessed directly in thymeleaf
        //For paging configuration, there is a method of page sub packaging
        page.setRows(discussPostService.findDiscussPostsRows(0));
        page.setPath("/index");

        //Paging query, top ten
        List<DiscussPost> discussPostList =  discussPostService.findDiscussPosts(0,page.getOffset(),page.getLimit());
        //Post list
        List<Map<String,Object>> discussPosts = new ArrayList<>();
        if(discussPostList != null){
            //Traverse each post
            //Associate posts with users
            for(DiscussPost post : discussPostList){
                Map<String,Object> map = new HashMap<>();
                map.put("post",post);//Posts
//                System.out.println(post.getTitle());
                User user = userService.findUserById(post.getUserId());//Posting user
//                System.out.println(user.getUsername());
                map.put("user",user);
                discussPosts.add(map);
            }
        }

        //Add to view
        model.addAttribute("discussPosts",discussPosts);
        return "/index";

  Reuse paging:

<!-- paging -->
				<!-- Pagination is displayed only when there is data -->
				<nav class="mt-5" th:if="${page.rows>0}">
					<ul class="pagination justify-content-center">
						<li class="page-item">
							<a class="page-link" th:href="@{${page.path}(current=1,limit=10)}">home page</a>
						</li>
						<!-- If the current page is 1, you can't click it-->
						<li th:class="|page-item ${page.current==1?'disabled':''}|">
							<a class="page-link" th:href="@{${page.path}(current=${page.current-1})}">previous page</a></li>

						<!--Produce a continuous array-->
						<!--Lights up the current page-->
						<li th:class="|page-item ${i==page.current?'active':''}|" th:each="i:${#numbers.sequence(page.from,page.to)}">
							<a class="page-link" href="#" th:text="${i}">1</a>
						</li>
						<!--The current page is the last, so you can't click it-->
						<li th:class="|page-item ${page.current==page.total?'disabled':''}|">
							<a class="page-link" th:href="@{${page.path}(current=${page.current+1})}">next page</a>
						</li>
						<li class="page-item">
							<a class="page-link" th:href="@{${page.path}(current=${page.total})}">Last </a>
						</li>
					</ul>
				</nav>

1.7 project commissioning skills

Topics: Java JavaEE Maven Spring Tomcat