Spring boot case study: employee addition, deletion, modification and query page (fool teaching)

Spring boot case study: employee addition, deletion, modification and query page (fool teaching)

As the saying goes, no matter how many concepts you see, it's better to do a case study. This article will take you to learn and complete a Spring boot case.

To learn, we must first find the motivation before we have the perseverance to learn. If we look at the finished products first, we will have the motivation to do it. So let me first show you our case page here.

Allen's employee addition, deletion, modification and query page display

Attach the source code of the complete case

Link: https://pan.baidu.com/s/1mG3Rsj6T8KH7KREscHe5Rg
Extraction code: x9vb
After copying this content, open Baidu online disk mobile App, which is more convenient to operate

Actual combat 1: visit the login page by default and switch between Chinese and English (internationalization)

prepare documents

Attach the html files and css files we need

Link: https://pan.baidu.com/s/10nmAwLxDm6u1fl2BonN3TQ
Extraction code: cvt2
After copying this content, open Baidu online disk mobile App, which is more convenient to operate

Default access login page

Write a mymvcconfig class

package com.guo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
        registry.addViewController("/main.html").setViewName("dashboard");
    }
}

Pay attention to the location of the file here.

The html files not available here are the following contents. The html files are placed in the templates package and the others in the static package

Here is a fallible point. Joining you did not succeed in your visit. It may be that you haven't imported thymeleaf. As I said before, if you haven't imported thymeleaf, the web page will take effect only under these paths.

Static path:

"classpath:/META-INF/resources/", 
"classpath:/resources/", 
"classpath:/static/",
"classpath:/public/"

If you want to know more, you can see my article on static resource import

internationalization

First, uniformly set the encoding of properties in the IDEA!

Write an internationalization configuration file and extract the internationalization page messages that need to be displayed on the page. We can go to the login page to see what we need to write international configuration!

Configuration file writing

(this part comes from the spring boot teaching of crazy God)

1. We create a new i18n directory under the resources resource file to store the internationalization configuration files

2. Create a login Properties file and a login_zh_CN.properties; It is found that IDEA automatically identifies the internationalization operation we want to do; The folder has changed!

3. We can create a new file on it;

The following page pops up: let's add another one in English;

This is much faster!

4. Next, let's write the configuration. We can see another view under the idea**

In this view, we can directly add attributes by clicking the + sign; Let's create a new login Tip, you can see that there are three file boxes on the side for input

Let's add the content of the home page!

Then add other page contents in turn!

Then check our configuration file;

login.properties: default

login.btn=Sign in
login.password=password
login.remember=Remember me
login.tip=Please login
login.username=user name

login_en_US.properties: English

login.btn=Sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username

login_zh_CN.properties: Chinese

login.btn=Sign in
login.password=password
login.remember=Remember me
login.tip=Please login
login.username=user name

OK, the configuration file steps are completed!

Modify the value of the landing page to thymeleaf format

Then let's review the usage of thymeleaf

thymeleaf format:

Add one at the beginning of the html file:

<html lang="en"  xmlns:th="http://www.thymeleaf.org">

The format is:

th: select = '@ {path}'

For example:

<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">

Then use the thymeleaf template in the page where we need to switch between Chinese and English (of course, you can also use others)

I take my index HTML as an example

<!DOCTYPE html>
<html lang="en-US" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
		<meta name="description" content="">
		<meta name="author" content="">
		<title>Signin Template for Bootstrap</title>
		<!-- Bootstrap core CSS -->
		<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
		<!-- Custom styles for this template -->
		<link th:href="@{/css/signin.css}" rel="stylesheet">
	</head>

	<body class="text-center">
		<form class="form-signin" action="dashboard.html">
			<img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
			<input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
			<label class="sr-only">Password</label>
			<input type="password" class="form-control" th:placeholder="#{login.password}" required="">
			<div class="checkbox mb-3">
				<label>
          <input type="checkbox" value="remember-me">[[#{login.remember}]]</label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button>
			<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
			<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">chinese</a>
			<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
		</form>
	</body>
</html>

be careful:

Get value with#

Link path is@

We notice that we have prepared two Chinese and English buttons for this actual battle. A link is written in the button, which is the same in the front. However, we notice that the parameter in the brackets in thymeleaf is passed, which is equivalent to assigning a value to l. what's the use of assigning a value? We customize the LocaleResolver configuration and rewrite the methods in it

Write an internationalization class and inject it into Beans

MyLocaleResolver.class

package com.guo.config;

import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

public class MyLocaleResolver implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request){
        //Gets the language parameter in the request
        String language = request.getParameter("l");
        Locale locale=Locale.getDefault();
        //If requested link
        if(!StringUtils.isEmpty(language)){
            //division
            String[] split = language.split("_");
            //countries and regions 
        locale=new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}

MyMvcConfig.class

package com.guo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
    //Customized internationalization takes effect
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

The above code summary is just one sentence. If the value of l is not empty, press "" to obtain the value of l To split into two versions, the first as a country, the second as a region, and finally use these two parameters to new a locale object.

For example, if I order Chinese, l gets value zh_CN, split zh and CN, and then new object.

Actual combat 2: login implementation

Problems to be solved:

1. Determine whether the user name and password are correct

2. Redirect to main HTML page

Determine whether the user name and password are correct

Write a logincontroller class

package com.guo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpSession;

@Controller
public class LoginController {
    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        Model model, HttpSession session){

        if(!StringUtils.isEmpty(username)&&"123456".equals(password)){
            session.setAttribute("loginUser",username);
            return "redirect:/main.html";
        }
        else {
            model.addAttribute("msg","Wrong user name or password!");
            return "index";
        }

    }
}

Let's analyze it bit by bit. First

 public String login
     (@RequestParam("username")  String username,
      @RequestParam("password")  String password,
      Model model,
      HttpSession session)

Here's where we get the data

if(!StringUtils.isEmpty(username)&&"123456".equals(password))

Here, judge whether the user name is empty, and then judge whether the password is 123456. If so, execute

session.setAttribute("loginUser",username);

Assign loginUser to username

What if the user name is empty or the password is incorrect?

model.addAttribute("msg","Wrong user name or password!");

Pass msg the parameter "wrong user name or password!", But what's the use?

Let's go back to index Add one more to him in HTML

<p style="color: red" th:text="${msg}"  th:if="${not #strings.isEmpty(msg)}"></p>

When msg is not empty, we display msg information in red.

Redirect to main HTML page

return "redirect:/main.html";

Some people may ask why to redirect here. That's because our form is sent out in the form of get. Our user name and password will be attached to the link bar of successful login. (of course, you can also modify the form submission method to get)

Actual combat 3: interceptor

Create interceptor

First, we build a loginhandlerinterceptor class to implement the HandlerInterceptor interface.

public class LoginHandlerIntercepter implements HandlerInterceptor

Override the preHandle method inside:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception

Create a new object for him to judge whether he has successfully logged in.

Object loginUser = request.getSession().getAttribute("loginUser");//Once we log in successfully, we have a loginUser

If loginUser is empty, it proves that our user name is empty or the password is wrong, then we pass the value "no permission, please log in safely first" to msg. And let him stay on the index home page. Returns false.

Returns true if you are logged in securely.

if(loginUser==null) {
    request.setAttribute("msg", "No security permission, please log in first");
    request.getRequestDispatcher("/index.html").forward(request,response);
    return false;
}
else {
    return true;
}

Register interceptor

After our class is written, we will inject it into beans. Let's go back to Mymvcconfig:

@Overridepublic void addInterceptors(InterceptorRegistry registry) {    registry.addInterceptor(new LoginHandlerIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login");}

Error prone point

At this time, we saw that there was no css on my web page. When we opened it, we found that the css was blocked.

So where did we go wrong? Let's go back to mymvcconfig class

@Overridepublic void addInterceptors(InterceptorRegistry registry) {    registry.addInterceptor(new LoginHandlerIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login");}

Therefore, we need to release it in the code. We intercept all resources under the port, except "/ index.html" and "/" and "/ user/login", so we only need to add our static resources

@Overridepublic void addInterceptors(InterceptorRegistry registry) {    registry.addInterceptor(new LoginHandlerIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/css/**","/img/**");}

If a friend finds that the css still can't be loaded, he guesses that the friends use Google browser

Clean up the cache

Clean up the cache

That's it.

Practice 4: public page extraction

thymeleaf public page element extraction

1. Extract public segments

<footer th:fragment="copy" id="sidebar">
    &copy;2021 The thyme virtual grocery
</footer>

Two reference methods:

~{templatename::selector}   namely"footer::#sidebar "template name:: selector
~{templatename::fragment}   namely"footer::copy"Template name::Fragment name

Three approaches:

Let's choose template name: fragment name first

<div th:insert="footer::copy"></div>
<div th:replace="footer::copy"></div>
<div th:include="footer::copy"></div>

1. Insert is an insert

effect:

<div th:insert="footer::copy">
    <footer th:fragment="copy" id="sidebar">
    	&copy;2021 The thyme virtual grocery
	</footer>
</div>

We found that he inserted our public part in the middle of div.

2. replace is a substitute

<footer th:fragment="copy" id="sidebar">
	&copy;2021 The thyme virtual grocery
</footer>

We found that the div is missing, so replace depends directly on the part we inserted, and the original div will be replaced.

3. include is included

<div th:fragment="copy" id="sidebar">
	&copy;2021 The thyme virtual grocery
</div>

We found that we kept the original div, but the content in div was replaced by the content in footer.

Extract the top bar and side bar

Let's create a new commons package, which is placed under the new bar html

Let's go HTML and dashboard Extract the common part of HTML and put it into bar html

bar.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--topbar-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
    <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" th:href="@{/user/logout}">cancellation</a>
        </li>
    </ul>
</nav>
<!--sidebar-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" id="sidebar">
    <div class="sidebar-sticky">
        <ul class="nav flex-column">
            <li class="nav-item">
                <a class="nav-link" th:class="${activeUri=='main.html'?'nav-link active':'nav-link'}" th:href="@{/main.html}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
                        <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
                        <polyline points="9 22 9 12 15 12 15 22"></polyline>
                    </svg>
                    <span class="sr-only">(current)</span>
                    Dashboard
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
                        <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
                        <polyline points="13 2 13 9 20 9"></polyline>
                    </svg>
                    Orders
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart">
                        <circle cx="9" cy="21" r="1"></circle>
                        <circle cx="20" cy="21" r="1"></circle>
                        <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
                    </svg>
                    Products
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" th:href="@{/emps}"
                    th:class="${activeUri=='emps'?'nav-link active':'nav-link'}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users">
                        <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                        <circle cx="9" cy="7" r="4"></circle>
                        <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                        <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                    </svg>
                    Employee management
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2">
                        <line x1="18" y1="20" x2="18" y2="10"></line>
                        <line x1="12" y1="20" x2="12" y2="4"></line>
                        <line x1="6" y1="20" x2="6" y2="14"></line>
                    </svg>
                    Reports
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers">
                        <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                        <polyline points="2 17 12 22 22 17"></polyline>
                        <polyline points="2 12 12 17 22 12"></polyline>
                    </svg>
                    Integrations
                </a>
            </li>
        </ul>

        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
            <span>Saved reports</span>
            <a class="d-flex align-items-center text-muted" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
            </a>
        </h6>
        <ul class="nav flex-column mb-2">
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Current month
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Last quarter
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Social engagement
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Year-end sale
                </a>
            </li>
        </ul>
    </div>
</nav>
</body>
</html>

Of course, put the dashboard HTML and list Delete the corresponding part of HTML and change to these two codes

<!--introduce topbar-->
<div th:replace="commons/bar::topbar"></div>
<!--introduce sidebar-->
<div th:replace="commons/bar::#sidebar"></div>

Just refresh

Actual Combat 5: link highlighting and list completion

First, let's solve it

Link highlight

When we go to different pages, we also highlight the corresponding labels, but the menu bar next to the sidebar was made by common extraction, so how do we know which page he jumped to.

First, let's take a look at:

Highlighted label:<a class="nav-link active">
Unlit label<a class="nav-link">

Reference sidebar variables:

dashboard.html:

<div th:replace="commons/bar::#sidebar(activeUri='main.html')"></div>

list.html:

<div th:replace="commons/bar::#sidebar(activeUri='emps')"></div>

bar. Judgment in HTML:

dashboard label:

<a class="nav-link" th:class="${activeUri=='main.html'?'nav-link active':'nav-link'}" th:href="@{/main.html}">

Employee management label:

<a class="nav-link" th:href="@{/emps}" th:class="${activeUri=='emps'?'nav-link active':'nav-link'}">

Here I talk about a place that is easy to make mistakes. Many students asked me that after he finished, his icon is like this, which is the top to the front, and he highlights it no matter which page.

Error prone point

That's because you mistyped the highlighted label and the unlit label.

Please check if you have typed these two

<a class="nav-Link active">
<a class="nav-Link">

Please note that if the Link here is capitalized, it will highlight the front of the top by default.

After modification, the correct is as follows:

Let's solve how to judge which page it is. We can pass the value of a variable in the sidebar position of dashboard and bar, and then we can set the highlighted class or non highlighted class for our label according to its value.

Next, let's look at

List complete

<h2><a class="btn btn-sm btn-success" th:href="@{/emp}">Employee addition</a></h2>
					<div class="table-responsive">
						<table class="table table-striped table-sm">
							<thead>
							<tr>
								<th>#</th>
								<th>lastName</th>
								<th>email</th>
								<th>gender</th>
								<th>department</th>
								<th>birth</th>
								<th>operation</th>
							</tr>
							</thead>
							<tbody>
							<tr th:each="emp:${emps}">
								<td th:text="${emp.id}"></td>
								<td >[[${emp.lastName}]]</td>
								<td th:text="${emp.email}"></td>
								<td th:text="${emp.gender==0?'female':'male'}"></td>
								<td th:text="${emp.department.departmentName}"></td>
								<td th:text="${#dates.format(emp.birth,'yyyy-MM-dd HH:mm')}"></td>
								<td>
									<button class="btn-sm btn-primary">edit</button>
									<button class="btn-sm btn-danger">delete</button>
								</td>
							</tr>
							</tbody>
						</table>
					</div>

We explain part by part:

Overhead button

<h2><a class="btn btn-sm btn-success" th:href="@{/emp}">Employee addition</a></h2>
class-sucess//Green button th:href="@{/emp}" / / link to emp

Employee list

<tbody>		<tr th:each="emp:${emps}">				<td th:text="${emp.id}"></td>				<td >[[${emp.lastName}]]</td>				<td th:text="${emp.email}"></td>				<td th:text="${emp.gender==0?'female':'male'}"></td>				<td th:text="${emp.department.departmentName}"></td>				<td th:text="${#dates. format(emp.birth,'yyyy-MM-dd HH:mm')}"></td> 				< td> 					< Button class = "BTN SM BTN primary" > Edit < / button > 					< Button class = "BTN SM BTN danger" > delete < / button > 				</ td> 		</ tr></tbody>
<tr th:each="emp:${emps}">//Each traversal takes out each individual in the emps set for emp

Pick a few key points

Gender

<td th:text="${emp.gender==0?'female':'male'}"></td>//If the value received by gender is 0, it returns female, and 1 returns male

department

<td th:text="${emp.department.departmentName}"></td>//What is returned is the departmentName in the department object in emp

Birth

<td th:text="${#dates. Format (EMP. Birth, 'yyyy MM DD HH: mm')} "> < / td > / / set the return format to yyyy MM DD HH: mm

Edit and delete buttons

<td>	<button class="btn-sm btn-primary">edit</button>//Blue 	< Button class = "BTN SM BTN danger" > delete < / button > / / the warning button is red</td>

Practice 6: adding employees

Add page

<form th:action="@{/emp}" method="post">
	<div class="form-group">
		<label>LastName</label>
		<input name="lastName" type="text" class="form-control" placeholder="zhangsan">
    </div>
	<div class="form-group">
		<label>Email</label>
		<input name="email" type="email" 		class="form-control" placeholder="zhangsan@atguigu.com">
	</div>
	<div class="form-group">
		<label>Gender</label><br/>
		<div class="form-check form-check-inline">
			<input class="form-check-input" type="radio" name="gender"  value="1">
			<label class="form-check-label">male</label>
		</div>
		<div class="form-check form-check-inline">
			<input class="form-check-input" type="radio" name="gender"  value="0">
			<label class="form-check-label">female</label>
		</div>
	</div>
	<div class="form-group">
         <label>department</label>
		<select class="form-control" name="department.id">
<!--Submitted by Department id-->
		<option th:value="${dept.id}" th:each="dept:${depts}" th:text="${dept.departmentName}"></option>
		</select>
	</div>
	<div class="form-group">
		<label>Birth</label>
		<input name="birth" type="text" class="form-control" placeholder="zhangsan">
	</div>
	<button type="submit" class="btn btn-primary">add to</button>
</form>

We explain part by part

LastName

<div class="form-group">
	<label>LastName</label>
	<input name="lastName" type="text" class="form-control" placeholder="zhangsan">
</div>
<label>LastName</label>Label called LastName
name="lastName"//The value passed in is given to lastName
type="text"//Enter text
placeholder="zhangsan" //Prompt for expected value of input field

Email

<div class="form-group">
	<label>Email</label>
	<input name="email" type="email" class="form-control" placeholder="zhangsan@atguigu.com">
</div>
<label>Email</label>//The label is Email
name="email"//The value passed in to email
type="eail"//Enter email. Email format is required
placeholder="zhangsan@atguigu.com" //Prompt for expected value of input field

Gender

<div class="form-group">
		<label>Gender</label><br/>
		<div class="form-check form-check-inline">
			<input class="form-check-input" type="radio" name="gender"  value="1">
			<label class="form-check-label">male</label>
		</div>
		<div class="form-check form-check-inline">
			<input class="form-check-input" type="radio" name="gender"  value="0">
			<label class="form-check-label">female</label>
		</div>
</div>
<label>Gender</label>//The label is Gender
type="radio"//Single choice
//There are male and female options
//Select male to pass the value of 1 to gender, and select female to pass the value of 0
		<div class="form-check form-check-inline">
			<input class="form-check-input" type="radio" name="gender"  value="1">
			<label class="form-check-label">male</label>
		</div>
		<div class="form-check form-check-inline">
			<input class="form-check-input" type="radio" name="gender"  value="0">
			<label class="form-check-label">female</label>
		</div>

department

<div class="form-group">
         <label>department</label>
		<select class="form-control" name="department.id">
<!--Submitted by Department id-->
		<option th:value="${dept.id}" th:each="dept:${depts}" th:text="${dept.departmentName}"></option>
		</select>
</div>
<label>department</label>//The tag is called departmentname="department" / / the value passed in is given to department ID < Select > < option > < / option > < / Select > / / drop-down selection th:each="dept:${depts}" / / each is used here, which means that the depts set is traversed through each individual, which is a deptth:text="${dept.departmentName} / / all department names are displayed in the selection th:value="${dept.id} "/ / when we select, the value is not the departmentName of dept, but the ID of the Department.

Birth

<div class="form-group">		<label>Birth</label>		<input name="birth" type="text" class="form-control" placeholder="zhangsan"></div>
<label>Birth</label>//The tag is called Birthname="birth" / / the value passed in is given to birthtype="text" / / the text box type placeholder="zhangsan" / / enter the prompt of the expected value of the field

There are places to pay attention to here. Pay attention to the format of the date. The default is yyyy/MM/dd.

Change date to another format

Two methods:

1. In the configuration file application Modify on properties

spring.mvc.format.date=yyyy-MM-dd

2. Modify in the Employee class:

@DateTimeFormat(pattern = "yyyy-MM-dd")private Date birth;

The methods annotated by the two methods in the class take precedence over those modified in the configuration file

Display page

Save employee object first

At present, the last id of all employees is 1005 and the next id is 1006, so set an initId value

    private static Integer initId=1006;

EmployeeDao.class

Add the following code

   public void save(Employee employee){        if(employee.getId()==null){//Because the employee id is not set in our addition, there is no new addition, so it must be null employee setId(initId++);// We assign the value of initid to the newly added employee. After the assignment, initid will automatically increase to prepare for the addition of the next employee} employee setDepartment(departmentDao.getDepartmentById(employee.getDepartment(). getId()));// I'll focus on this because many students may not understand employees put(employee.getId(),employee);// Add the newly added employee object to the employees collection}

Tell me about this code

employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));

First, we go back to the code in the department part of the form, and we find that

<div class="form-group">         <label>department</label>		<select class="form-control" name="department.id"><!--Submitted by Department id-->		<option th:value="${dept.id}" th:each="dept:${depts}" th:text="${dept.departmentName}"></option>		</select></div>

The parameter we pass in is the id of the Department

How do we get this id?

1,employee.getDepartment() obtains a department object without department name first

 public Department getDepartment() {        return department;    }

2. We use department Getid gets the Department id of the employee object

    public Integer getId() {        return id;    }

3. Let's look at the department number corresponding to the id stored in the Department table. It uses departmentdao Getdepartmentbyid method

public Department getDepartmentById(Integer id){    return departments.get(id);}

departments. The get() method is the get() method of HashMap to obtain the corresponding value of the specified key pair.

department table

 private  static Map<Integer, Department> departments=null;    static {        departments=new HashMap<Integer,Department>();//Create a department table departments Put (101, new Department (101, "teaching department"); departments.put(102,new Department(102, "marketing department"); departments.put(103,new Department(103, "teaching and research department"); departments.put(104,new Department(104, "operation Department"); departments.put(105,new Department(105, "logistics department");}

4. Finally, get the assignment of department to employee Setdepartment() method

Judge whether the data is added successfully.

EmployeeController.class

Add the following code

 @PostMapping("/emp")    public String addEmp(Employee employee){        System.out.println("Saved employee information:"+employee);//        Save employee employeedao save(employee);//         Go to the employee list page / / redirect: redirect to an address / / forward: forward to an address return "redirect:/emps";}

Final effect:

Practice 7: deletion and cancellation

Delete operation

realization:

1. Click to delete the object (EmployeeDao.delete method)

2. After deletion, the employee list page remains

list.html modify the following code:

<button type="submit" class="btn btn-primary">modify</button>

become

<a class="btn-sm btn-danger" th:href="@{/delemp/}+${emp.id}">delete</a>

I can't change it to button. Why can't I change it to button

EmployeeController.class add

 @GetMapping("/delemp/{id}")
    public String deleteEmployee(@PathVariable("id") Integer id){
        employeeDao.delete(id);
        return "redirect:/emps";
    }

Logoff operation

realization:

1. Empty the session information inside

2. Jump back to landing page

Modify bar html

<a class="nav-link" th:href="@{/user/logout}">cancellation</a>

Modify LoginController

@RequestMapping("/user/logout")
public String logout(HttpSession session){
    session.invalidate();
    return "redirect:/index.html";
}

Some students may not know what session is?

When the browser requests for the first time, the server creates a session object and generates a sessionId at the same time. In this response, the sessionId will be used as a response message The whole session can be maintained by sending it back to the client browser memory or rewriting the url.

And session Invalidate() is to set the session to invalidate

Finally, redirect to the login page (index.html)

Practice 8: modify employee information

Button modification

list.html modify the following code

<button class="btn-sm btn-primary">edit</button>

become:

<a class="btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">edit</a>

Jump writing

Clicking the Edit button will jump to the link of / emp / modified employee id

Let's do another getmapping and finally return to our update page

@GetMapping("/emp/{id}")
public String toEditPage(@PathVariable("id") Integer id,Model model){
    Employee employee = employeeDao.get(id);
    model.addAttribute("emp",employee);
    Collection<Department> departments = departmentDao.getDepartment();
    //Find out all departments and display them on the page
    model.addAttribute("depts",departments);
return "emp/update";
}

First, I get the employee object through this id

Let me pass this object to emp

Finally, I found out all the departments and assigned them to depts

Now I don't know why these operations are. Just look down.

Make update page

We put add Copy HTML and put it in the same directory (under emp)

Modify the following:

<form th:action="@{/updateEmp}" method="post">
	<input type="hidden" name="id" th:value="${emp.getId()}" >
	<div class="form-group">
		<label>LastName</label>
		<input name="lastName" type="text" class="form-control" placeholder="zhangsan" th:value="${emp.lastName}">
	</div>
	<div class="form-group">
		<label>Email</label>
		<input name="email" type="email" class="form-control" placeholder="zhangsan@atguigu.com" 			th:value="${emp.email}">
	</div>
	<div class="form-group">
	  <label>Gender</label><br/>
		<div class="form-check form-check-inline">
		  <input class="form-check-input" type="radio" name="gender" value="1" th:checked="${emp.getGender()==1}">
		  <label class="form-check-label">male</label>
	    </div>
	   <div class="form-check form-check-inline">
		 <input class="form-check-input" type="radio" name="gender"  value="0" th:checked="${emp.getGender()==0}">
		 <label class="form-check-label">female</label>
	   </div>
	</div>
	<div class="form-group">
		<label>department</label>
		<select class="form-control" name="department.id">
<!--Submitted by Department id-->
			<option th:selected="${dept.id==emp.department.id}" th:value="${dept.id}" th:each="dept:${depts}" th:text="${dept.departmentName}"></option>
		</select>
	</div>
	<div class="form-group">
		<label>Birth</label>
		<input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${#dates.format(emp.birth,'yyyy-MM-dd HH:mm')}">
	</div>
	<button type="submit" class="btn btn-primary">modify</button>
</form>

Let's choose some special ones:

Gender

 th:checked="${emp.getGender()==1}"male
 th:checked="${emp.getGender()==0}"female

th:checked checkbox echo

If gender is 1, the male label is selected and 0 is female

department

 th:selected="${dept.id==emp.department.id}" 

Select the department whose name is equal to the id in the department object in emp.

Some friends will ask me that there is nothing in their department box

OK, let me ask you what your dept is, and you say: my add page works normally.

That's because we passed the value of dept on the add page, but the new page partner didn't add it.

Let's go back and check the employeecontroller class

    @GetMapping("/emp/{id}")
    public String toEditPage(@PathVariable("id") Integer id,Model model){
        Employee employee = employeeDao.get(id);
        model.addAttribute("emp",employee);
        Collection<Department> departments = departmentDao.getDepartment();
        //Find out all departments and display them on the page
        model.addAttribute("depts",departments);
    return "emp/update";
    }

If we add it, we won't report an error. The correct one is just like that

birth

<div class="form-group">
	<label>Birth</label>
	<input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${#dates.format(emp.birth,'yyyy-MM-dd HH:mm')}">
</div>

Some students will ask why not use this directly

<input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${emp.birth}">

OK, let's run with the following one. When submitting, we report an error. Let's see the error report.

Console error

Field error in object 'employee' on field 'birth': rejected value [Sun Jun 13 00:00:00 CST 2021]; codes [typeMismatch.employee.birth,typeMismatch.birth,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [employee.birth,birth]; arguments []; default message [birth]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'birth'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value 'Sun Jun 13 00:00:00 CST 2021'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [Sun Jun 13 00:00:00 CST 2021]]]

The conclusion is just one sentence, 'Sun Jun 13 00:00:00 CST 2021' can't be passed into birth, so I'll change it back to yyyy mm DD

After modification, the modification is completed.

Error prone point

Let's modify the information and click the Modify button

We found that he added an id, but the effect we want is to modify the original employee information. That's when you remember us

EmployeeDao class

//The primary key increases automatically! private static Integer initId=1006;    // Add an employee public void save (employee) {if (employee. Getid() = = null) {employee. Setid (initid + +);} employee. setDepartment(departmentDao.getDepartmentById(employee.getDepartment(). getId()));         employees. put(employee.getId(),employee);    }

He didn't get his id, so null triggered the addition of a new object. Therefore, when we modify it, we should also take its original id, but the employee id is immutable and cannot be seen by the modifier. What should we do?

In update HTML add this code

<input type="hidden" name="id" th:value="${emp.getId()}" >

Finally, remember to modify his form submission method and place

update.html modification

<form th:action="@{/updateEmp}" method="post">

EmployeeController.class add

 @PostMapping("/updateEmp")    public String updateEmp(Employee employee){        employeeDao.save(employee);        return "redirect:/emps";    }

Keywords: Blockchain Spring Boot Back-end

Added by mwichmann4 on Sun, 30 Jan 2022 18:46:36 +0200