title: Regis Takeaway-Day02
abbrlink: '1'
date: 2023-04-1 19:30:00
St. Regis Takeaway-Day02
Course content
- Perfect login function
- new employee
- Employee Information Paging Query
- Enable/disable employee accounts
- Edit employee information
Analyze how the front-end page effect is achieved
Why does clicking on the left and right change the root?
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-WwJYwseg-1688460908030)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304092100003.png)]
First of all, let's take a look at how the menu is displayed. Let's take a look at why the right side changes when the menu is clicked.
First: how the menu is displayed
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-a6J6csVc-1688460908031)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304092101695.png)]
When we create a VUE object, we prepare a menuList: [] in our data() position. menuList: [] is an array object
Each JSON data is placed in the array object, and each JSON data contains id name url icon (icon) The above is just the preparation of data, not the definition, so it can be displayed in a position of the menu
<script>
new Vue({
el: '#app',
data() {
return {
defAct: '2',
menuActived: '2',
userInfo: {
},
menuList: [
// {
// id: '1',
// name: '门店管理',
// children: [
{
id: '2',
name: '员工管理',
url: 'page/member/list.html',
icon: 'icon-member'
},
{
id: '3',
name: '分类管理',
url: 'page/category/list.html',
icon: 'icon-category'
},
{
id: '4',
name: '菜品管理',
url: 'page/food/list.html',
icon: 'icon-food'
},
{
id: '5',
name: '套餐管理',
url: 'page/combo/list.html',
icon: 'icon-combo'
},
{
id: '6',
name: '订单明细',
url: 'page/order/list.html',
icon: 'icon-order'
}
// ],
// },
],
iframeUrl: 'page/member/list.html',
headTitle: '员工管理',
goBackFlag: false,
loading: true,
timer: null
}
},
computed: {
},
created() {
const userInfo = window.localStorage.getItem('userInfo')
if (userInfo) {
this.userInfo = JSON.parse(userInfo)
}
this.closeLoading()
},
beforeDestroy() {
this.timer = null
clearTimeout(this.timer)
},
mounted() {
window.menuHandle = this.menuHandle
},
methods: {
logout() {
logoutApi().then((res)=>{
00
if(res.code === 1){
localStorage.removeItem('userInfo')
window.location.href = '/backend/page/login/login.html'
}
})
},
goBack() {
// window.location.href = 'javascript:history.go(-1)'
const menu = this.menuList.find(item=>item.id===this.menuActived)
// this.goBackFlag = false
// this.headTitle = menu.name
this.menuHandle(menu,false)
},
menuHandle(item, goBackFlag) {
this.loading = true
this.menuActived = item.id
this.iframeUrl = item.url
this.headTitle = item.name
this.goBackFlag = goBackFlag
this.closeLoading()
},
closeLoading(){
this.timer = null
this.timer = setTimeout(()=>{
this.loading = false
},1000)
}
}
})
</script>
menuList: [ menuList: [] 是一个数组对象 数组对象 //120行
{ 里面放着一个个JSON数据
id: '2', 每一个JSON数据里面又放着id name url icon(图标)
name: '员工管理',
url: 'page/member/list.html',
icon: 'icon-member'
},
{
id: '3',
name: '分类管理',
url: 'page/category/list.html',
icon: 'icon-category'
},
{
id: '4',
name: '菜品管理',
url: 'page/food/list.html',
icon: 'icon-food'
},
{
id: '5',
name: '套餐管理',
url: 'page/combo/list.html',
icon: 'icon-combo'
},
{
id: '6',
name: '订单明细',
url: 'page/order/list.html',
icon: 'icon-order'
}
// ],
// },
],
Some of the names are 'employee management', 'category management', 'dish management', 'package management', 'order details', which correspond to the ones shown in the figure below.
The above is just the preparation of data, not the definition, which can be displayed in a position of the menu
Second, how to display the position of the menu
Please go to line 39 and use the v-for under the el-menu component to indicate that it is traversing the menuList
<el-submenu :index="item.id" v-if="item.children && item.children.length>0">
这里面的 v-if是不会成立的 但是会执行第64行<el-menu-item v-else :index=“item.id” @click=“menuHandle(item,false)”>这个分支 然后就可以把{ {item.name}} item.name给展示出来
<el-menu //菜单组件
:default-active="defAct"
:unique-opened="false"
:collapse-transition="false"
background-color="#343744"
text-color="#bfcbd9"
active-text-color="#f4f4f5"
> //item不是固定写法
<div v-for="item in menuList" :key="item.id"> //v-for表示在遍历 遍历menuList
//判断item里面有没有children属性和children属性的length是否大于0
//我们往下看到第126那里的每一项都没有我们的children
// 但是会执行第64行<el-menu-item v-else :index="item.id" @click="menuHandle(item,false)">这个分支 // 然后就可以把第66行的item.name给展示出来 如果我们把id修改成Id
<el-submenu :index="item.id" v-if="item.children && item.children.length>0">
<template slot="title">
<i class="iconfont" :class="item.icon"></i>
<span>{
{item.name}}</span>
</template>
<el-menu-item
v-for="sub in item.children"
:index="sub.id"
:key="sub.id"
@click="menuHandle(sub,false)"
>
<i :class="iconfont" :class="sub.icon"></i>
<span slot="title">{
{sub.name}}</span>
</el-menu-item
>
</el-submenu>
//64行 <el-menu-item v-else :index="item.id" @click="menuHandle(item,false)">
<i class="iconfont" :class="item.icon"></i>
//66行 <span slot="title">{
{item.name}}</span> //把item.name给展示出来
</el-menu-item>
</div>
</el-menu>
所以我们看到的就是以下的名称
如果我们把name修改成id
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VueK0LVa-1688460908036)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02/202304092342644.png)]
重启 刷新
为什么是Id 因为由这个对象数组menuList:[]决定
`new Vue({
el: '#app',
data() {
return {
defAct: '2',
menuActived: '2',
userInfo: {},
menuList: [
// {
// id: '1',
// name: '门店管理',
// children: [
{
id: '2',
name: '员工管理',
url: 'page/member/list.html',
icon: 'icon-member'
},
{
id: '3',
name: '分类管理',
url: 'page/category/list.html',
icon: 'icon-category'
},
{
id: '4',
name: '菜品管理',
url: 'page/food/list.html',
icon: 'icon-food'
},
{
id: '5',
name: '套餐管理',
url: 'page/combo/list.html',
icon: 'icon-combo'
},
{
id: '6',
name: '订单明细',
url: 'page/order/list.html',
icon: 'icon-order'
}
// ],
// },
],
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8eI3NKi-1688460908040)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02/202304092344576.png)]
第三 : 点击菜单时 右边会跟着变
http://localhost:8080/backend/index.html
这些菜单实际上都加了一个@click事件 当我们点击菜单的事情 他会执行menuHandle() 方法
<el-menu-item v-else :index="item.id" @click="menuHandle(item,false)">
然后把item,false传过来 接下来我们找到menuHandle() 方法 在196行
menuHandle(item, goBackFlag) {
this.loading = true
this.menuActived = item.id
this.iframeUrl = item.url
this.headTitle = item.name
this.goBackFlag = goBackFlag
this.closeLoading()
},
当我们点击菜单的时候 就会执行menuHandle() 方法 这里面最重要的是 this.iframeUrl = item.url
这里面的url就是以下的url(128行) 也就是点击菜单的url
menuList: [
// {
// id: '1',
// name: '门店管理',
// children: [
{
id:'2',
name : '员工管理',
url: 'page/member/list.html',
icon: 'icon-member'
},
{
id: '3',
name: '分类管理',
url: 'page/category/list.html',
icon: 'icon-category'
},
{
id: '4',
name: '菜品管理',
url: 'page/food/list.html',
icon: 'icon-food'
},
{
id: '5',
name: '套餐管理',
url: 'page/combo/list.html',
icon: 'icon-combo'
},
{
id: '6',
name: '订单明细',
url: 'page/order/list.html',
icon: 'icon-order'
}
// ],
// },
],
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-FGiI0VQ9-1688460908045)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304100024943.png)]
This is to display a new page through iframeUrl
iframeUrl defined on line 158
iframeUrl: 'page/member/list.html',
Where will iframeUrl be used?
used on line 89
<iframe></iframe>
This is used to display a new page and where does this page come from
<iframe //用来展示一个新的页面
id="cIframe"
class="c_iframe"
name="cIframe"
:src="iframeUrl"
width="100%"
height="auto"
frameborder="0"
v-show="!loading"
></iframe>
This is equivalent to digging a hole on our page
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-HHPZH34n-1688460908048)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304100031207.png)]
And where does this page come from?
<iframe
id="cIframe"
class="c_iframe"
name="cIframe"
:src="iframeUrl" 这个地方传进什么数据 展示的就是什么数据
width="100%"
height="auto"
frameborder="0"
v-show="!loading"
></iframe>
Why do we show employee management instead of category management or others after we log in?
This is because we give the iframeUrl an initial value of
iframeUrl: 'page/member/list.html',
And when we click on the menu, we are actually switching the url
menuHandle(item, goBackFlag) {
this.loading = true
this.menuActived = item.id
this.iframeUrl = item.url
this.headTitle = item.name
this.goBackFlag = goBackFlag
this.closeLoading()
},
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-lsGTKVNm-1688460908051)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131532890.png)]
For example, we now modify the initial page to the following
iframeUrl: 'http://www.itcast.c
restart refresh
So when we click on the menu, he is actually switching the url address
And this url address has already been written when the data is prepared
menuList: [
// {
// id: '1',
// name: '门店管理',
// children: [
{
id:'2',
name : '员工管理',
url: 'page/member/list.html',
icon: 'icon-member'
},
{
id: '3',
name: '分类管理',
url: 'page/category/list.html',
icon: 'icon-category'
},
{
id: '4',
name: '菜品管理',
url: 'page/food/list.html',
icon: 'icon-food'
},
{
id: '5',
name: '套餐管理',
url: 'page/combo/list.html',
icon: 'icon-combo'
},
{
id: '6',
name: '订单明细',
url: 'page/order/list.html',
icon: 'icon-order'
}
// ],
// },
],
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-k2oreBW7-1688460908054)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304100044727.png)]
Different menus correspond to different pages, so when we click on a certain menu, it actually switches to the corresponding page
1. Improve the login function
1.1 Problem Analysis
Previously, we have completed the development of the employee login function of the background system, but there is still a problem. Next, we will explain this problem and how to deal with it.
1). Current status
If the user does not log in and directly visits the home page of the system, it can still be accessed normally.
2). Ideal effect
The above design is unreasonable. The effect we want to see should be that the pages in the system can only be accessed after successful login. If there is no login, any interface in the system will directly jump to the login page.
So, how should it be realized?
It can be realized by using the filters and interceptors we explained before, intercepting the requests initiated by the front end in the filters and interceptors, and judging whether the user has logged in. If not, return a prompt message and jump to the login page.
1.2 Thought Analysis
The specific processing logic of the filter is as follows:
A. Get the URI of this request
B. Determine whether this request needs to be logged in before it can be accessed
C. If not required, release directly
D. Judging the login status, if it is already logged in, it will be released directly
E. If not logged in, return the result of not logged in
If not logged in, what kind of results do we need to return to the front end? At this time, we can go to see how the front end handles it?
1.3 Code implementation
Implementation steps:
1. Create a custom filter LoginCheckFilter
2. Add the annotation @ServletComponentScan to the startup class
3. Improve the processing logic of the filter
1). Define the login verification filter
Customize a filter LoginCheckFilter and implement the Filter interface, and complete the verification logic in the doFilter method. Then, we will complete the specific function code implementation according to the above analysis steps:
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-tEBf2g8a-1688460908057)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131533933.png)]
package com.itheima.reggie.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*检查用户是否已经完成登录*/
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//强转
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到请求:{}",request.getRequestURI());
//放行
filterChain.doFilter(request,response);
}
}
reboot
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-JcYZhW6y-1688460908060)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131533957.png)]
to refresh
Code explanation:
explain one
This code is a filter (Filter) in a Java Web application. Filters preprocess the request or response before the request reaches the target Servlet/JSP, so that some operations are done before the actual request is processed.
The function of this filter is to check whether the user has logged in, by checking whether the URL is used to log in the user's authentication information, such as session ID, token, etc. If the user is not logged in, the filter will redirect the user to the login page, if the user is already logged in, the request will be passed to the next handler.
Specifically, this filter implements the doFilter method in the Filter interface. This method receives parameters of ServletRequest and ServletResponse types, and converts them into HttpServletRequest and HttpServletResponse types through type conversion. It then prints a log indicating that the request was intercepted and passes the request and response objects to the FilterChain. Finally, the filter chain passes the request and response objects to the next handler.
In short, this filter is a very useful tool, it can pre-process the user request before reaching the target Servlet/JSP, to ensure that the user has completed the login and has been authorized, thereby protecting the security of the Web application.
Explanation two
When we use a Java web application, we need to make sure that users are logged in and authorized, otherwise they will not be able to access pages that require special permissions. That's what this code does.
This code implements a filter (Filter), which will preprocess the request before reaching the target Servlet/JSP. It checks if the user is already logged in, and if not, it redirects the user to the login page so the user can complete the login, then tries again to access the page that requires special permissions.
This filter checks the requested URL, and if the URL contains the user's authentication information, such as a session ID or token, then it considers the user to be logged in. If the user has not completed the login, it redirects to the login page for the user to complete the login.
The implementation of this filter is relatively simple, it implements the doFilter method in the Filter interface. When a request arrives, it converts the request into an HttpServletRequest object and checks whether the login has been completed. If the login is already done, it passes the request and response objects to the next handler. If the login is not completed, it redirects the user to the login page.
All in all, this filter is a useful tool for securing web applications by ensuring that users are logged in and authorized.
Explanation three
This code is a filter (Filter) in a Java Web application, and its function is to check whether the user has completed the login operation before the user visits any web page.
In the code, the @WebFilter annotation is used, the name of the filter is specified as "loginCheckFilter", and it is applied to all URLs, namely "/*".
In the doFilter() method, convert the incoming ServletRequest and ServletResponse objects into HttpServletRequest and HttpServletResponse objects, record the URL address of the current request, and finally hand over the request and response objects to FilterChain for further processing.
The function of Filter is similar to an interceptor. When a user visits any webpage, the filter will first intercept the request and check whether the user has logged in. If the user has completed the login operation, the filter will release the request and allow the user to continue to visit The page; if the user is not logged in, the filter redirects to the login page, requiring the user to log in before proceeding to the page.
In general, the role of this code is to protect sensitive resources in the Web application, to ensure that only users who have completed the login operation can access these resources, which improves the security of the system.
Understanding: Why is there a forced transfer in this code
In this code, we convert the ServletRequest and ServletResponse objects into HttpServletRequest and HttpServletResponse objects, because the doFilter method of the Filter interface receives ServletRequest and ServletResponse objects, and we need to use HttpServletRequest and HttpServletResponse object to get the HTTP request and response related information.
ServletRequest and ServletResponse are interfaces defined in the Java Servlet Specification that provide a general way of handling HTTP requests and responses. But they lack some methods of HttpServletRequest and HttpServletResponse objects, such as getParameter and getAttribute, which are defined in HttpServletRequest and HttpServletResponse interfaces.
Therefore, in order to be able to use these specific methods, we need to cast the ServletRequest and ServletResponse objects into HttpServletRequest and HttpServletResponse objects, so that these specific methods can be used. However, before casting, we need to make sure that the request is indeed an HTTP request, otherwise the casting may cause a type conversion exception.
Two annotations: explanation of @WebFilter and @Slf4j
The @WebFilter annotation is used to mark a class as a filter (Filter), which can specify the name of the filter (filterName) and the URL pattern (urlPatterns). In this example, we set the name of the filter as "loginCheckFilter" and specify the URL pattern as "/*", that is, intercept all requests.
The @Slf4j annotation is one of the annotations provided in the Lombok framework, which is used to simplify the logging code. It will automatically generate a logger called "log" at compile time, which we can use to log. In this example, we use the log.info method to log information.
These annotations are used to help us write code and implement functions more conveniently. The @WebFilter annotation makes it easier for us to define a filter and specify the requests that need to be intercepted. The @Slf4j annotation helps us implement the logging function more conveniently.
Detailed explanation of each line of code
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
This line of code declares a filter using the @WebFilter annotation, specifies the name of the filter as "loginCheckFilter", and applies it to all URLs, namely "/*".
@Slf4j
This line of code uses the @Slf4j annotation provided by Lombok to automatically generate a log object named log, which can be used to output log information.
public class LoginCheckFilter implements Filter {}
This line of code is the declaration of the doFilter() method, which is a method in the Filter interface and is used to intercept user requests and process them.
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
This line of code converts the incoming ServletRequest and ServletResponse objects into HttpServletRequest and HttpServletResponse objects for subsequent processing of requests and responses.
log.info("拦截到请求:{}", request.getRequestURI());
This line of code uses the previously defined log object to output a log message, recording the URL address of the current request, which is convenient for subsequent debugging and problem location.
filterChain.doFilter(request, response);
This line of code calls the doFilter() method of the FilterChain object, and passes the processed request and response objects to the next filter or Servlet for processing. If there are no other filters, they are directly handed over to the Servlet for processing. In this way, a chain of filters is formed, ensuring that each request is processed by multiple filters.
review filter filter
explain one
HTTP Request --> Filter 1 --> Filter 2 --> ... --> Filter n --> Servlet --> HTTP Response
In a Java web application, a filter (Filter) is a component used to process HTTP requests and responses. They are used to intercept requests and modify request parameters, headers or body, and response information as needed. Filters can be processed before or after the servlet executes, or while the servlet is processing.
When an HTTP request arrives at the servlet container, it is first intercepted by any registered filters. Filters can alter the request as needed, or pass the request to the next filter. Once all filters have processed the request, the final target servlet is invoked. After the servlet processes the request, it generates a response, which is processed through the same chain of filters, and the response can be modified at each filter.
The order of this filter chain is defined in the web.xml file, and filters can be added or removed dynamically. This allows developers to customize the request processing process as needed, enabling more flexible and complex application functions.
Package: com.itheima.reggie.filter
import com.alibaba.fastjson.JSON;
import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否已经完成登录
*/
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter{
//路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、获取本次请求的URI
String requestURI = request.getRequestURI();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//4、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
filterChain.doFilter(request,response);
return;
}
log.info("用户未登录");
//5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
/**
* 路径匹配,检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}
return false;
}
}
AntPathMatcher extensions:
Introduction: The path matcher provided in Spring;
Wildcard rules:
symbol meaning ? matches a character * matches 0 or more characters ** matches 0 or more directories/characters
2). Enable component scanning
It is necessary to add the annotation of Servlet component scanning to the boot class to scan the @WebFilter annotation of the filter configuration. After scanning, the filter will take effect at runtime.
@Slf4j
@SpringBootApplication
@ServletComponentScan
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class,args);
log.info("项目启动成功...");
}
}
The role of @ServletComponentScan:
In the SpringBoot project, after adding this annotation to the boot class/configuration class, it will automatically scan the @WebServlet, @WebFilter, @WebListener annotations in the project (under the current package and its subpackages), and automatically register the relevant components of the Servlet ;
1.4 Functional test
When we directly enter
http://localhost:8080/backend/login.html
hour
Will jump to the login interface
http://localhost:8080/backend/page/login/login.html
The front-end JS of the video is different from our actual front-end
After the code is written, we need to restart the project, then directly enter the home page of the system management background in the address bar of the browser, and then check whether it can jump to the login page. We can also track the process of code execution in the form of debug.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ncOlWYT3-1688460908063)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021802532.png)]
For the front-end code, debugging can also be performed.
F12 opens the browser's debugging tool, finds the request.js we mentioned earlier, and puts a breakpoint at the response interceptor of request.js.
2. New employees
2.1 Demand Analysis
Employee information can be managed in the background system, and background system users can be added by adding new employees. Click the [Add Employee] button to jump to the new page, as follows:
After filling in the form information and clicking the "Save" button, the data of the form will be submitted to the server, and the server needs to accept the data, and then save the data to the database.
2.2 Data Model
Adding new employees is actually inserting the employee data entered on our new page into the employee table. The status field in the employee table has been set to a default value of 1, indicating that the status is normal.
It should be noted that a unique constraint is added to the username field in the employee table, because username is the employee's login account and must be unique.
2.3 Program execution flow
Before developing the code, we need to combine the requests initiated by the front-end page to sort out the execution process of the entire program:
A. Click the "Save" button, the page sends an ajax request, and submits the data entered in the new employee page to the server in the form of json, the request method is POST, and the request path is /employee
B. The server controller receives the data submitted by the page and calls Service to save the data
C. Service calls Mapper to operate the database and save data
2.4 Code implementation
Add the save method in EmployeeController to save user employee information.
A. When adding an employee, the requirement description in the button page prototype needs to set an initial default password of 123456 for the employee, and encrypt the password with MD5.
B. When assembling employee information, it is also necessary to encapsulate the creation time, modification time, creation person, and modification person information (obtain the current login user from the session).
/*新增员工*/
@PostMapping
public R<String> save(@RequestBody Employee employee){
log.info("新增员工,员工信息:{}",employee.toString());
return null;
}
Ensure that the request sent by the front-end page can be requested to the save method and the submitted parameters can be submitted to the employee object
@RequestBody: Used to obtain the JSON string submitted by the client (front end) and convert the ISON string into a javabeen entity class
@RespomseBody: javabeen entity class converted to JSON
Employee: Use the Employee object to receive the request parameters passed by the front end (JSON format)
R: return value
General explanation 1
This code is a controller method that uses the Spring framework to process HTTP POST requests and map the data in the request body to Employee objects to add employees.
Let's explain the code line by line:
@PostMapping
: This is an annotation used to map this method to the HTTP POST request method. It indicates that this method will handle POST requests from clients.public R<String> save(@RequestBody Employee employee)
: This is the declaration of the method. It receives aEmployee
parameter of type which will be extracted from the request body.@RequestBody
The annotation tells the Spring framework to take JSON data from the request body and convert it intoEmployee
an object.log.info("新增员工,员工信息:{}", employee.toString())
: This line of code uses logging to record the operation of adding an employee.log.info()
method is used to print information, and use placeholders{}
toemployee.toString()
insert the return value of 's into the log information. This allows you to view the details of the newly added employee in the console or in the log file.return null
: This method returns anull
value. You can return an appropriate response according to actual needs, such as returning a success message or the ID of the new employee.
So, when you send a HTTP POST request to the URL of this controller, the data in the request body will be mapped to the Employee
object, and the employee's information will be printed in the log. The method will then return a null
value in response. You can modify the method body according to your needs, execute appropriate business logic or return corresponding results.
General explanation 2
This code is an interface for new employee functions of the employee management system based on the SpringBoot framework.
Among them, the @PostMapping annotation indicates that the interface only accepts POST requests. The @RequestBody annotation indicates that the JSON format data in the request body is bound to the Employee object. The Employee object represents an employee's information, including attributes such as employee ID, name, gender, and position. When receiving the POST request from the client, SpringBoot will automatically convert the JSON format data in the request body into the corresponding Employee object, and assign it to the method parameter employee.
Inside the method, use log.info to print out the newly added employee information. Finally, the type returned by the interface is R, which represents a custom response class, where R represents the response result, and String represents the content of the response message. In this example, the interface returned null. Null needs to be replaced with the corresponding response result according to actual business needs.
In short, the main function of this code is to receive the employee information submitted by the client and write it to the database, record the log and return the response result.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-GkG6Hg4I-1688460908065)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306051054661.png)]
/**
* 新增员工
* @param employee
* @return
*/
@PostMapping
public R<String> save(HttpServletRequest request,@RequestBody Employee employee){
log.info("新增员工,员工信息:{}",employee.toString());
//设置初始密码123456,需要进行md5加密处理
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
//获得当前登录用户的id
Long empId = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empId);
employee.setUpdateUser(empId);
employeeService.save(employee);
return R.success("新增员工成功");
}
code explanation 1
This code is a controller method using the Spring framework to handle HTTP POST requests and add employees.
Let's explain the code line by line:
@PostMapping
: This is an annotation that maps this method to the HTTP POST request method.public R<String> save(HttpServletRequest request, @RequestBody Employee employee)
: This is the declaration of the method. It receives two parameters:HttpServletRequest request
andEmployee employee
.@RequestBody
Annotations tell the Spring framework to take data from the request body and convert it intoEmployee
an object.HttpServletRequest
Parameters are used to get information about the current request.log.info("新增员工,员工信息:{}", employee.toString())
: This line of code uses logging to record the operation of adding an employee. Employee information isemployee.toString()
converted to a string and inserted into the log information.employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()))
: This line of code sets the employee's initial password to "123456" and encrypts it with MD5.DigestUtils.md5DigestAsHex()
method converts a byte array to an MD5 hashed string.employee.setCreateTime(LocalDateTime.now())
: This line of code sets the current time as the employee's creation time.employee.setUpdateTime(LocalDateTime.now())
: This line of code sets the current time as the employee's update time.Long empId = (Long) request.getSession().getAttribute("employee")
: This line of code gets an attribute named "employee" from the current session, which represents the ID of the currently logged in user.employee.setCreateUser(empId)
andemployee.setUpdateUser(empId)
: These two lines of code set the ID of the currently logged in user as the employee's create user and update user.employeeService.save(employee)
: This line of code calls the methodemployeeService
of the servicesave()
to save the newly added employee information.return R.success("新增员工成功")
: This line of code returns a successful response, containing a "New employee successful" message.
To sum up, this code processes an HTTP POST request, maps the data in the request body to an Employee
object, and performs a series of processing on the object, such as setting the initial password, setting the creation time and update time, setting the creation user and updating the user wait. Finally, call employeeService
the save()
method to save the employee information and return a successful response message.
Code Explanation 2
This code is an interface for the new employee function of the employee management system based on the SpringBoot framework, which adds some business logic processing compared to the previous code.
Among them, the @PostMapping annotation indicates that the interface only accepts POST requests. The @RequestBody annotation indicates that the JSON format data in the request body is bound to the Employee object. HttpServletRequest request represents HTTP request information. The Employee object represents an employee's information, including attributes such as employee ID, name, gender, and position.
Inside the method, use log.info to print out the newly added employee information. Next, some preprocessing operations are performed on the employee object:
- Set the initial password 123456, and encrypt it with MD5 and store it in the employee object;
- Get the current time and set it as the creation time and update time respectively;
- Get the id of the currently logged in user from the session, and set it as the user creation and update user;
Finally, call the employeeService.save() method to write the employee information into the database, and return a custom response class R when the interface returns, where success indicates the status of success, and "new employee succeeded" indicates the content of the response message.
In short, the main function of this code is to receive the employee information submitted by the client and write it into the database, and perform some preprocessing operations. At the same time record the log and return the response result.
Test new employees
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-TLxlqAru-1688460908067)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131535557.png)]
There will be problems if you enter a zhagsan
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-sYFBDM4l-1688460908070)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131535685.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-oakWy0Xb-1688460908072)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306052104630.png)]
2.5 Functional test
After the code is written, we need to restart the project. After the completion, directly visit the homepage of the management system, click the "Add Employee" button on the "Employee Management" page, enter the basic information of the employee, and then click "Save" to save the data. After saving , to check whether the employee data is entered in the database.
When we add a user in the test and enter an existing user name, an error message appears on the front-end interface:
At this time, the server has reported an error, and the error message is as follows:
The above error occurs mainly because in the employee table structure, we have established a unique index for the username field. When adding duplicate username data, if the constraint is violated, an error will be reported. But at this time, the information prompted by the front end is not specific, and the user does not know what caused the exception. We need to prompt the user with detailed error information.
2.6 Global exception handling
2.6.1 Idea Analysis
In order to solve the problems in the above tests, we need to capture the exceptions that may occur in the program. There are usually two ways to deal with them:
A. Add try...catch to the Controller method for exception capture
The form is as follows:
If this method is used, although it can be solved, there are disadvantages. When we save other business data, we also need to add try...catch to the Controller method for processing. The code is redundant and not universal.
B. Use exception handlers for global exception capture
In this way, we only need to define a general global exception handler in the project to resolve all exceptions in this project.
2.6.2 Global exception handler
Customize a global exception handler in the project, add the annotation @ControllerAdvice to the exception handler, and specify which type of Controller method to intercept through attribute annotations. And add the annotation @ExceptionHandler to the method of the exception handler to specify which type of exception is intercepted.
Exception handling method logic:
- Specify the caught exception type as SQLIntegrityConstraintViolationException
- Parse the exception prompt information, and get the value that violates the unique constraint
- Assemble the error message and return
/**
* 全局异常处理
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
/**
* 异常处理方法
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
return R.error("失败了");
}
}
Code explanation 1:
The above code is a class for global exception handling. This class uses Spring's @ControllerAdvice annotation to identify it as a global exception handler. Through this annotation, it intercepts exceptions that occur in classes annotated by @RestController and @Controller annotations.
The specific explanation is as follows:
@ControllerAdvice(annotations = {RestController.class, Controller.class})
: This is a class-level annotation used to specify the annotation type of the Controller class to be intercepted by the global exception handling class. Here, it specifies that the class to be intercepted must be a class marked with @RestController or @Controller annotation.@ResponseBody
: This is a method-level annotation, indicating that the return value of this method will be directly returned to the client as the content of the response, rather than being parsed into a view by the view resolver. Here, it ensures that the return value of the exception handling method will be converted to the JSON format of the response.@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
: This is a method-level annotation that specifies the specific exception type to be handled by the method. Here, it specifies that the exception to be handled by the method is SQLIntegrityConstraintViolationException.public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex)
: This is the exception handling method, which receives a parameter of type SQLIntegrityConstraintViolationException, which represents the caught exception object. The return type of the method is R, and R is a custom generic response object used to wrap the response data.log.error(ex.getMessage())
: This line of code uses the logging function provided by Slf4j to record the abnormal error message to the log.return R.error("失败了")
: This line of code returns an R object representing the response result after handling the exception. Use the R.error static method to create an R object of type error and set the error message to "failed".
综上所述,以上代码定义了一个全局异常处理类,用于捕获和处理Controller层中发生的SQLIntegrityConstraintViolationException异常,并将错误信息记录到日志中,最后返回一个错误类型的响应结果。
代码解释2
这段代码是一个基于SpringBoot框架的全局异常处理类,用于捕获并处理SQL异常。
@ControllerAdvice注解表示该类用于全局异常处理。通过annotations参数指定了需要拦截的控制器注解类型为@RestController和@Controller。@ResponseBody注解表示返回的是JSON格式的数据。@Slf4j注解表示使用log记录日志。
@ExceptionHandler注解表示该方法用于捕获SQLIntegrityConstraintViolationException类型的异常。当系统出现SQLIntegrityConstraintViolationException类型的异常时,会调用该方法进行异常处理。在方法内部,使用log.error打印异常信息,并返回一个自定义的响应类R,其中error表示失败的状态,"失败了"表示响应消息的内容。
总之,这段代码的主要作用是实现对SQLIntegrityConstraintViolationException类型异常的统一捕获和处理。当系统出现该类型的异常时,会执行该方法进行异常处理,并记录日志并返回响应结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGQEzmmS-1688460908073)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02/202306131536773.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-zDnZxiTx-1688460908074)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131536460.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-m2WjK5TB-1688460908076)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131536013.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-gT3qFPmr-1688460908076)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131536837.png)]
Package: com.iheima.reggie.common
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.SQLIntegrityConstraintViolationException;
/**
* 全局异常处理
*/
@ControllerAdvice(annotations = {
RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
/**
* 异常处理方法
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
if(ex.getMessage().contains("Duplicate entry")){
String[] split = ex.getMessage().split(" ");
String msg = split[2] + "已存在";
return R.error(msg);
}
return R.error("未知错误");
}
}
Notes:
The two annotations @ControllerAdvice and @ResponseBody used on the above global exception handler are as follows:
@ControllerAdvice : Specifies which types of controllers to intercept;
@ResponseBody: convert the return value R object of the method into data in json format, and respond to the page;
The two annotations used above can also be combined into one annotation @RestControllerAdvice
code explanation 1
The above code is a Java class that contains an GlobalExceptionHandler
exception handling class named . This class contains a exceptionHandler
method named , which receives a SQLIntegrityConstraintViolationException
type of exception as a parameter.
In exceptionHandler
the method, first use log.error(ex.getMessage())
the method to save the exception message to the log. Then, use ex.getMessage()
the method to get the exception message and split it into multiple strings for further processing.
If the exception message contains a string "Duplicate entry"
, the method will use split()
the method to split the string into multiple strings, and then get the 3rd string from it, which is usually details describing the presence of duplicates. Finally, the method will use error()
the method to convert the details into R<String>
a response of type and return that response. If the exception message contains other strings, the method will return R.error("未知错误")
a response of type .
It should be noted that @ExceptionHandler
the annotations in this code are used to specify the type of exception handled and return R<String>
the type of data. This annotation needs to @RestController
be used with annotations to integrate exception handling with RESTful API.
explaining in detail
The annotation in the above code @ExceptionHandler
is an exception handling annotation, which is used to specify which type of exception to handle. In this example, @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
the method is specified to handle SQLIntegrityConstraintViolationException
exceptions of type.
@ExceptionHandler
The annotation takes one parameter, the type of exception to handle. In this example, SQLIntegrityConstraintViolationException
is the exception type we want to handle. When the program encounters such an exception, it will be passed to exceptionHandler
the method for handling.
exceptionHandler
A method is a return value method that receives a SQLIntegrityConstraintViolationException
type of exception as a parameter. Inside the method, we first use log.error(ex.getMessage())
the method to save the exception message to the log. We then use ex.getMessage()
the method to get the exception message and split it into multiple strings.
If the exception message contains a string "Duplicate entry"
, the method will use split()
the method to split the string into multiple strings, and then get the 3rd string from it, which is usually details describing the presence of duplicates. In this example, we pass the 3rd string as a parameter to error()
the method to convert the details into R<String>
a typed response. If the exception message contains other strings, the method will return R.error("未知错误")
a response of type .
Finally, we need to integrate exception handling with the RESTful API. In this example, @RestController
the annotation specifies that the controller handles RESTful API requests. So when the program encounters an exception, it will be passed to the exception handling function in the RESTful API controller. In this case, the function uses @ExceptionHandler
annotations to specify the type of exception to handle and returns an error response.
Code Explanation 2
The above code is a global exception handler, which is used to catch the exception thrown in the controller marked by @RestController or @Controller, and return the error message in a unified format.
Among them, the @ControllerAdvice annotation indicates that this class is a global exception handler, the @ResponseBody annotation indicates that the returned result is data in JSON format, and @Slf4j is a Slf4j logging tool, which is often used to output log information.
In terms of code implementation, the @ExceptionHandler annotation is used to specify the type of exception handled and return data of type R.
The processing flow of this code is: when an exception of SQLIntegrityConstraintViolationException is caught, if the exception information contains the words "Duplicate entry", it is considered to be an exception of data duplication, the specific data is extracted from the exception information, and then a message containing the information is returned Data of type R; otherwise, an "unknown error" data of type R is returned.
Code Explanation 3
The above code is a global exception handling class that uses the @ControllerAdvice annotation provided by the Spring framework. This class is used to catch and handle exceptions thrown in controllers.
Annotations in the code @ControllerAdvice(annotations = {RestController.class, Controller.class})
indicate that the class will only handle exceptions that occur in controllers annotated with @RestController
or .@Controller
The annotation @ResponseBody
indicates that the result returned by the method of this class will be returned directly as the response body instead of being parsed as a view by the view resolver. It is to convert javabeen into JSON and return
@Slf4j
is a Lombok annotation for automatically generating loggers.
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
Indicates that the method will handle SQLIntegrityConstraintViolationException
exceptions of type. In the method, it first records the error message of the exception, and then checks whether the error message contains "Duplicate entry", and if so, generates the corresponding error message according to the content of the error message and returns an object (possibly R
custom response object).
If the error message does not contain "Duplicate entry", an object containing the default error message is returned R
.
It's worth noting that this line of code in the code 返回 R.error(msg);
is pseudocode and should actually return an R
object. In this case, R.error(msg)
a pseudocode that means return an object with an error msg
message R
. The specific R
object implementation and usage methods need to be defined and processed according to the actual situation.
Summary: The above code is a global exception handling class for catching and handling exceptions thrown in the controller SQLIntegrityConstraintViolationException
. According to the error message of the exception, it generates the corresponding error message and returns an R
object (pseudo-code) used to represent the exception handling result.
explain in detail
When developing with the Spring framework, we often need to handle exceptions that may be thrown in the controller to provide better error handling and friendly error responses. The global exception handling class is used for this purpose.
First, we can use @ControllerAdvice
annotations to identify a class as a global exception handling class. In this example, the annotation uses annotations
attributes specifying the type of controller annotation that needs to be processed as @RestController
and @Controller
.
Next, use @ExceptionHandler
the annotation to identify a method as an exception handler. In this case, the method handles SQLIntegrityConstraintViolationException
an exception of type .
In the exception handling method, we first use @Slf4j
the annotation to generate a logger to record the exception's error message.
Next, we check whether the exception's error message contains "Duplicate entry", that is, whether it is an exception thrown because of a violation of the uniqueness constraint (Duplicate entry). If so, we extract the corresponding information from the error message and generate a new error message based on that information.
In this example, we use ex.getMessage().contains("Duplicate entry")
to check whether the error message contains "Duplicate entry", and then use ex.getMessage().split(" ")
to split the error message by spaces to obtain relevant information.
After generating a new error message, we R.error(msg)
create a response object with msg
the error message. Here R.error()
is a pseudocode that returns a response object with an error message.
If the error message does not contain "Duplicate entry", it means other unknown errors, and we return a default error response object, which contains a default error message indicating an unknown error.
It should be noted that 返回 R.error(msg);
this line of code in the code is pseudocode, and should actually return an R
object, and the specific return method needs to be defined and processed according to the actual situation.
By using this global exception handling class, we can centrally handle the specified types of exceptions thrown in the controller and provide custom error responses. This simplifies code logic and provides a unified exception handling mechanism to improve system robustness and user experience.
When we add an existing value
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-yYdGR7gY-1688460908077)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131537709.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-LPG10VAA-1688460908078)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131537244.png)]
When we add a value that does not exist
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ZxaVZMON-1688460908079)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131537941.png)]
2.6.3 Testing
After the global exception handler is written, we need to restart the project, and then directly visit the homepage of the management system, and click the "Add Employee" button on the "Employee Management" page. When we add a user in the test and enter an existing user name, the front-end interface displays the following error message:
3. Employee page query
3.1 Demand Analysis
When there are a lot of employees in the system, it will be messy to display all of them on one page, which is not easy to view. Therefore, in general systems, the list data will be displayed in a page-by-page manner. In our pagination query page, in addition to the pagination condition, there is also a query condition such as the query "employee name".
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-Dgn6vaVn-1688460908081)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021803131.png)]
-
request parameters
-
Search criteria: employee name (fuzzy query)
-
Pagination conditions: number of items displayed on each page, page number
-
-
response data
- total
-
result list
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-gbQrUaTx-1688460908082)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131538518.png)]
1). The page sends an ajax request, and submits the pagination query parameters (page, pageSize, name) to the server
F12 refresh page
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-kXxtcVB6-1688460908083) (C:\Users\zyz\AppData\Roaming\Typora\typora-user-images\ image-20230605221909418.png)]
page=1&pageSize=10 Check the first page and check 10 data in total
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-p1zw7eSO-1688460908084)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131538788.png)]
Look at the front-end code
Why is the request sent out as soon as it is loaded?
<script>
new Vue({
el: '#member-app',
data() {
return {
input: '',
counts: 0,
page: 1,
pageSize: 2,
tableData : [],
id : '',
status : '',
}
},
computed: {},
created() {
this.init()
if(localStorage.getItem('userInfo') != null){
//获取当前登录员工的账号,并赋值给模型数据user
this.user = JSON.parse(localStorage.getItem('userInfo')).username
}
},
mounted() {
},
methods: {
async init () {
const params = {
page: this.page,
pageSize: this.pageSize,
name: this.input ? this.input : undefined
}
await getMemberList(params).then(res => {
if (String(res.code) === '1') {
this.tableData = res.data.records || []
this.counts = res.data.total
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
},
handleQuery() {
this.page = 1;
this.init();
},
// 添加
addMemberHandle (st) {
if (st === 'add'){
window.parent.menuHandle({
id: '2',
url: '/backend/page/member/add.html',
name: '添加员工'
},true)
} else {
window.parent.menuHandle({
id: '2',
url: '/backend/page/member/add.html?id='+st,
name: '修改员工'
},true)
}
},
//状态修改
statusHandle (row) {
this.id = row.id
this.status = row.status
this.$confirm('确认调整该账号的状态?', '提示', {
'confirmButtonText': '确定',
'cancelButtonText': '取消',
'type': 'warning'
}).then(() => {
enableOrDisableEmployee({ 'id': this.id, 'status': !this.status ? 1 : 0 }).then(res => {
console.log('enableOrDisableEmployee',res)
if (String(res.code) === '1') {
this.$message.success('账号状态更改成功!')
this.handleQuery()
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
})
},
handleSizeChange (val) {
this.pageSize = val
this.init()
},
handleCurrentChange (val) {
this.page = val
this.init()
}
}
})
</script>
The above code is a front-end page script written using the Vue framework. It creates a Vue instance, which contains some data and methods.
data
First, some data is defined in the properties of the Vue instance , including input
(the value of the input box), counts
(the total number of data), page
(the current page number), pageSize
(the amount of data displayed on each page), tableData
(table data), id
(employee ID), status
(employee status), etc.
In created
the lifecycle hook function, userInfo
assign the account number of the currently logged-in employee to user
the data by reading the browser's local storage (localStorage).
In mounted
the life cycle hook function, you can perform some operations that need to be performed after the page is loaded, but there is no specific logic in this code snippet.
Next is the definition of some methods:
init
Method: This method is used to initialize the page data. ItgetMemberList
obtains the employee list data by calling the function, and assigns the returned data totableData
andcounts
.handleQuery
Method: When the user clicks the query button,page
reset the page number ( ) to 1, and then callinit
the method to reload the data.addMemberHandle
Method: used to handle the operation of adding or modifying employees. According to the incoming parameterst
(can be 'add' or employee ID), call thewindow.parent.menuHandle
method to open the corresponding page to add or modify employees.statusHandle
Method: Used to handle account state changes. First assign the employee's ID and status toid
andstatus
, and then pop up a confirmation dialog box. After confirming the adjustment of the account status, callenableOrDisableEmployee
the function to send a request to change the employee's status. If the request is successful, a success message is displayed andhandleQuery
the method is called to reload the data.handleSizeChange
Method: When the user changes the amount of data displayed on each page, assign the new data amount topageSize
, and then callinit
the method to reload the data.handleCurrentChange
Method: When the user changes the current page number, assign the new page number topage
, and then callinit
the method to reload the data.
To sum up, the above code mainly implements a front-end page for employee management, including functions such as employee list display, query, addition, modification, and account status change.
function getMemberList (params) {
return $axios({
url: '/employee/page',
method: 'get',
params
})
}
The above code defines a getMemberList
function named , which takes a params
parameter named .
This function uses $axios
an object (probably a library that encapsulates an Ajax request) to send a GET request to the requested URL /employee/page
. The parameters of the request params
are passed using an object, and the method of the request is set to GET.
After the function is executed, a Promise object will be returned, and the result or error of the request can be processed through the .then()
method .catch()
.
In short, this function is used to send a GET request to the specified URL, and the parameters are the parameters in params
the object to obtain the data of the employee list.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-d7wxrkJk-1688460908085)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131538116.png)]
3.2 Program execution flow
3.2.1 Page flow analysis
Before developing the code, you need to sort out the execution process of the entire program.
A. Click the menu to open the employee management page, execute the query:
B. Enter the employee's name in the search bar, press Enter, and execute the query:
1). The page sends an ajax request, and submits the pagination query parameters (page, pageSize, name) to the server
2). The server controller receives the data submitted by the page, and assembles the conditions to call the Service to query the data
3). Service calls Mapper to operate the database and query paged data
4). The Controller will respond to the paged data queried to the front-end page
5). The page receives the paged data and displays it on the page through the Table component of ElementUI
3.2.2 Front-end code introduction
1). When accessing the employee list page /member/list.html, the hook method in Vuejs will be triggered, and the created method will be called when the page is initialized
From the above front-end code, we can see that after executing the pagination query, the information we need to return to the front-end needs to contain two items: the list of results encapsulated in records, and the total number of records encapsulated in total.
When assembling the request parameters, page and pageSize are the parameters when the front-end paging plug-in renders;
2). In the getMemberList method, initiate an asynchronous request through axios
The asynchronous request initiated by axios will be intercepted by the request interceptor declared in request.js, in which the get request will be further packaged and processed
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-sBOP16Mi-1688460908087)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021804051.png)]
The final request sent to the server is: GET request, request link /employee/page?page=1&pageSize=10&name=xxx
3.3 Code implementation
3.3.1 Paging plugin configuration
Currently we want to implement the paging query function, but to implement the paging function in MybatisPlus, we need to use the paging plug-in provided in MybatisPlus. To use the paging plug-in, we must declare the bean object of the paging plug-in in the configuration class.
Belonging package: com.iheima.reggie.config
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置MP的分页插件
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//创建了一个`MybatisPlusInterceptor`对象
//`MybatisPlusInterceptor`是MyBatis-Plus框架提供的拦截器,可以在执行MyBatis的SQL语句过程中添加额外的功能。
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//通过调用`addInnerInterceptor`方法,将一个`PaginationInnerInterceptor`对象作为内部拦截器添加到`MybatisPlusInterceptor`中。`PaginationInnerInterceptor`是MyBatis-Plus提供的分页插件,它能够拦截SQL语句,并根据传入的分页参数自动进行分页查询。
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
code explanation 1
The above code is a Java class used to configure the paging plug-in of MyBatis-Plus (MP for short).
@Configuration
The annotation indicates that this is a configuration class used to configure some components or functions of the application.MybatisPlusConfig
A named Bean method is defined in the classmybatisPlusInterceptor
to create and return anMybatisPlusInterceptor
object.MybatisPlusInterceptor
It is an interceptor provided by MyBatis-Plus, which is used to intercept the SQL execution process of MyBatis and add additional functions during the execution process.addInnerInterceptor
Add anPaginationInnerInterceptor
object asMybatisPlusInterceptor
an internal interceptor by calling a method.PaginationInnerInterceptor
It is a paging plug-in provided by MyBatis-Plus, which can automatically intercept SQL statements and perform paging queries according to the incoming paging parameters. AfterPaginationInnerInterceptor
adding it toMybatisPlusInterceptor
, you can realize automatic pagination of query results.@Bean
The annotation indicates that the object returned by the method is registered as a Spring Bean, which can be used in other components through dependency injection.
To sum up, the above code configures the paging plug-in of MyBatis-Plus, and realizes the automatic paging function of MyBatis by creating MybatisPlusInterceptor
an object and adding it as an internal interceptor.PaginationInnerInterceptor
be more detailed
When using the MyBatis-Plus framework for database operations, sometimes it is necessary to display query results in pages. The above code shows how to configure the paging plugin of MyBatis-Plus.
First, create a Java class and add @Configuration
annotations to indicate that this is a configuration class. The main purpose of this class is to configure the paging plugin of MyBatis-Plus.
In this configuration class, a mybatisPlusInterceptor
method named is defined and @Bean
marked with an annotation. This means that the object returned by this method will be registered as a Spring Bean and can be used in other components through dependency injection.
In mybatisPlusInterceptor
the method, an object is created MybatisPlusInterceptor
and configured. MybatisPlusInterceptor
It is an interceptor provided by the MyBatis-Plus framework, which can add additional functions during the execution of MyBatis SQL statements.
addInnerInterceptor
Add an PaginationInnerInterceptor
object to it as an internal interceptor by calling the method MybatisPlusInterceptor
. PaginationInnerInterceptor
It is a paging plug-in provided by MyBatis-Plus, which can intercept SQL statements and automatically perform paging queries according to the incoming paging parameters.
In this way, the automatic paging function of MyBatis is realized through the configured MybatisPlusInterceptor
internal interceptor .PaginationInnerInterceptor
To sum up, the above code configures the paging plug-in of MyBatis-Plus, so that when using MyBatis-Plus for database query, the paging operation can be conveniently performed, so that the query results can be displayed in batches on the page. In this way, developers do not need to manually write paging logic, but let the paging plug-in automatically intercept SQL statements and perform paging queries according to the incoming paging parameters, which simplifies the development process.
Code Explanation 2
This code implements the configuration of the MyBatis Plus pagination plugin. MyBatis Plus is an enhanced tool based on MyBatis, which provides some powerful functions while improving development efficiency, one of which is the pagination plug-in.
In this code, we define a MybatisPlusInterceptor instance and add a PaginationInnerInterceptor internal interceptor to it, which is used to implement the paging function. Finally, register the MybatisPlusInterceptor instance as a Bean in the Spring container to complete the configuration of the MyBatis Plus paging plugin.
Code Explanation 3
The above code is a configuration class of MyBatis-Plus, which defines a named mybatisPlusInterceptor
Bean. The role of this bean is to use the Pagination plug-in in MyBatis-Plus for pagination processing.
In mybatisPlusInterceptor
the method, we create a MybatisPlusInterceptor
new object called and return it. This object is an interceptor object that can be intercepted before or after executing SQL operations. Here, we add an internal interceptor PaginationInnerInterceptor
for pagination when query operations are performed.
PaginationInnerInterceptor
Is a custom internal interceptor, its function is to divide the query statement into multiple parts when executing the query operation, and perform paging processing on each part as needed. In this example, we set the size of each part to 10, which means that the size of each part is 10 records.
After returning MybatisPlusInterceptor
the object, we can define methods in the configuration file @Bean
to create the object. In this case, MybatisPlusConfig
the class is a configuration class that defines a @Bean
method mybatisPlusInterceptor
to create MybatisPlusInterceptor
objects.
By defining methods in the configuration file @Bean
to create MybatisPlusInterceptor
objects, we can automatically configure MyBatis-Plus at application startup for pagination when executing queries.
be more detailed
MyBatis-Plus is an open source persistence layer framework, which provides many functions, such as automatic table creation, dynamic SQL, transaction management and so on. Among them, the pagination plug-in is an important function provided by MyBatis-Plus, which can help developers to perform paging processing more conveniently.
The class in the above code MybatisPlusConfig
is a configuration class, which defines a @Bean
method mybatisPlusInterceptor
for creating MybatisPlusInterceptor
objects. This object is an interceptor object that can be intercepted before or after executing SQL operations. Here, we have added an internal interceptor PaginationInnerInterceptor
, its function is to divide the query statement into multiple parts when executing the query operation, and paginate each part as needed.
PaginationInnerInterceptor
is a custom internal interceptor that inherits from MyBatisPlusInterceptor
the class. MyBatisPlusInterceptor
Class is the default interceptor class provided by MyBatis-Plus, which provides some basic interception functions, such as SQL filtering, transaction management, exception handling and so on. In PaginationInnerInterceptor
the class, we override some of these methods, for example beforeQuery
, to do pagination before querying.
In beforeQuery
the method, we use String.split()
the method to split the query into parts and pass each part as a parameter to the method MyBatisPlusInterceptor
of beforeQuery
the . In beforeQuery
the method, we can use MapperScannerConfigurer
the class to scan and configure the Mapper interface to perform corresponding operations when querying.
Through the above code, we can implement the paging function in MyBatis-Plus without modifying the source code of MyBatis-Plus. @Bean
At the same time, we can also define methods in the configuration file to create MybatisPlusInterceptor
objects so that MyBatis-Plus can be automatically configured when the application starts, thereby improving the maintainability and scalability of the system.
3.3.2 Paging query implementation
As we have analyzed above, when the page performs pagination query, the specific request information is as follows:
ask | illustrate |
---|---|
request method | GET |
request path | /employee/page |
request parameters | page , pageSize , name |
So what kind of results do we need to return to the front end after the query is completed?
We also analyzed above that the result data returned by the query should encapsulate two pieces of information, namely: records encapsulates the paging list data, and total encapsulates the total number of records that meet the conditions. Then at this time, when defining the return value type R of the controller method, we can directly encapsulate and return the result Page of the MybatisPlus pagination query, because the properties in the Page are as follows:
Then, based on these known requirements and conditions, the code implementation of pagination query is completed. The specific logic is as follows:
A. Construct pagination conditions
B. Build search criteria - name for fuzzy matching
C. Build sorting conditions - sort in reverse order of update time
D. Execute the query
E. Assemble the result and return
records 结果列表
total 总记录数
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-CXUtqRG7-1688460908088)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131539429.png)]
Receive the response from the server
await getMemberList(params).then(res => {
if (String(res.code) === '1') {
this.tableData = res.data.records || []
this.counts = res.data.total
}
}
The data returned by the server
this.tableData = res.data.records || []
this.counts = res.data.total
This means that the JSON we respond to should have records total fields, but our Employee does not have these two fields, so the generic type we use in EmployeeController should be Page Page is a class encapsulated by MybatisPlus for us. We will perform paging query in a while. It will also return this object as shown below
In our Page, we have our .records and total attributes. Records is the list data displayed on the current page, the total total number of records, and the total number of records. So why we use Page here is because the data records and total are required on the page.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-hzsRlDjw-1688460908089)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131539517.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-7cVWiVjr-1688460908090)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131540157.png)]
public R<Page> page() {
return null;
}
/**
* 员工信息分页查询
* @param page 当前查询页码
* @param pageSize 每页展示记录数
* @param name 员工姓名 - 可选参数
* @return
*/
@GetMapping("/page")
public R<Page> page(int page ,int pageSize, String name) {
log.info("page = {},pageSize = {},name = {}" ,page,pageSize,name);
return null;
}
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-jryzYHDC-1688460908091)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131540813.png)]
Refresh the page and log in
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-lgQ7Anmi-1688460908092)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131540365.png)]
F8
let go
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-3yuxSMuq-1688460908092)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131540621.png)]
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-Nvr0TdpU-1688460908093)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131540085.png)]
The specific code implementation is as follows:
/**
* 员工信息分页查询
* @param page 当前查询页码
* @param pageSize 每页展示记录数
* @param name 员工姓名 - 可选参数
* @return
*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
log.info("page = {},pageSize = {},name = {}" ,page,pageSize,name);
//构造分页构造器
Page pageInfo = new Page(page,pageSize);
//构造条件构造器
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
//添加过滤条件
queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
//添加排序条件
queryWrapper.orderByDesc(Employee::getUpdateTime);
//执行查询
employeeService.page(pageInfo,queryWrapper);
return R.success(pageInfo);
}
code explanation 1
The above code is an interface method for employee information paging query in Java Spring Boot. Here is an explanation of the code:
@GetMapping("/page")
: This is the mapping path of a GET request, which is used to handle pagination query requests. The request path is/page
.public R<Page> page(int page, int pageSize, String name)
: This is a public method with a return type of ,R<Page>
that is, an object that wraps the response result. The method namepage
accepts three parameters:page
the page number of the current query,pageSize
the number of records displayed on each page,name
and the employee name (optional parameter).log.info("page = {},pageSize = {},name = {}", page, pageSize, name)
: This line of code is used to output the log and record the parameter value passed in.Page pageInfo = new Page(page, pageSize)
: This is a pagination constructor used to create a paging object, passing in the page number of the current query and the number of records displayed on each page.LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper()
: This is a condition constructor, which is used to construct the query condition object.queryWrapper.like(StringUtils.isNotEmpty(name), Employee::getName, name)
: This line of code adds a fuzzy query condition to perform fuzzy matching based on employee names (Employee
object attributes). It is used to judge whether the parameter is not empty, if not, add the fuzzy query condition; otherwise, do not add the condition.name
StringUtils.isNotEmpty(name)
name
queryWrapper.orderByDesc(Employee::getUpdateTime)
: This line of code adds a sorting condition to sort in descending order based on the employee's update time (a propertyEmployee
of the object ).updateTime
employeeService.page(pageInfo, queryWrapper)
: This line of code executes the query operation, callsemployeeService
thepage
method, passes in the paging object and query condition object, and encapsulates the query result intopageInfo
the object.return R.success(pageInfo)
: Finally, the object that encapsulates the query resultpageInfo
is used as the response result, andR.success()
returned after being wrapped by the method.
Generally speaking, this interface method accepts the parameters of the pagination query, builds the query condition according to the parameters, executes the query operation, and returns the paging object containing the query results.
What is StringUtils in this
StringUtils
Is a string processing tool class, usually a class in the Apache Commons Lang library. It provides many utility methods for processing strings, such as determining whether a string is empty, removing spaces in strings, comparing strings, etc.
In the code, StringUtils.isNotEmpty(name)
it is used to judge name
whether the parameter is empty. Returns if name
not empty true
; returns if name
empty or null false
. This judgment condition is used to decide whether to add the fuzzy query condition of employee name to the query condition.
It should be noted that StringUtils
classes can have different implementations, and which implementation to use depends on the libraries and versions introduced in the project.
Code Explanation 2
The above code is a simple Spring Boot application for paging query of employee information. Its function is to receive three parameters: the current query page number page, the number of records displayed on each page pageSize and employee name, and return a successful response PageInfo object.
Here is a detailed explanation of the code:
@GetMapping("/page")
The annotation specifies that the request path is /page, which is mapped topage
the method.log.info("page = {},pageSize = {},name = {}" ,page,pageSize,name)
In the method,log.info
the method is used to output the values of three parameters, which are the current query page number page, the number of records displayed on each page pageSize, and the employee name.Page pageInfo = new Page(page,pageSize)
A PageInfo object pageInfo is created, which is used to encapsulate paging information and query conditions. Among them,page
the parameter specifies the current query page number, andpageSize
the parameter specifies the number of records displayed on each page.LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper()
A LambdaQueryWrapper object queryWrapper is created, which is used to encapsulate query conditions. Among them,Employee
is the generic type of the employee information class, andname
the parameter specifies the name of the employee to be queried.queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name)
Added a filter that does fuzzy matching on employee names. Among them,StringUtils.isNotEmpty(name)
the method checks whether the name parameter is not empty, andEmployee::getName
the method refers to the class method getName of the employee information, which is used to return the employee name.queryWrapper.orderByDesc(Employee::getUpdateTime)
Added a sorting condition, that is, sorting in descending order by employee update time.employeeService.page(pageInfo,queryWrapper)
The page method of employeeService is called, which receives two parameters: pageInfo object and LambdaQueryWrapper object. The pageInfo object is used to encapsulate paging information and query conditions, and the LambdaQueryWrapper object is used to encapsulate query conditions.return R.success(pageInfo)
A successful response object R is returned, which contains paging information and query results.
To sum up, the above code implements a simple employee information paging query function, receiving three parameters: the current query page number page, the number of records displayed on each page pageSize and employee name, and returns a successful response PageInfo object.
Code Explanation 3
The above code is an employee information paging query API interface in a Java SpringBoot project, which is mainly used to query the list of employees who meet the specified conditions and display them in paging. The specific explanation is as follows:
- The @GetMapping(“/page”) annotation indicates that this interface handles GET requests and registers the path mapping of /page.
- The three parameters page, pageSize and name respectively represent the current query page number, the number of records displayed on each page and the employee name (optional), and these parameters will be passed in as the request parameters of the interface.
- Page pageInfo = new Page(page, pageSize) Assign a value to the pageInfo object, page is the current page number, pageSize is the number of records displayed on each page, this line of code constructs a page constructor object and passes in these two parameters, and then assigns it Give pageInfo.
- LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() Constructs a condition constructor for building SQL query statements.
- queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name) Add a conditional filter to queryWrapper, if name is not empty, query the employee data whose name contains name. Among them
Employee::getName
, means to use the getName method of the Employee entity class to perform filtering operations. - queryWrapper.orderByDesc(Employee::getUpdateTime) Adds sorting conditions to queryWrapper, sorting employees in descending order according to their update time. Where
Employee::getUpdateTime
means to use the getUpdateTime method of the Employee entity class for sorting operations. - employeeService.page(pageInfo,queryWrapper) Execute the query, store the query result in the pageInfo object, and finally return pageInfo.
- Finally, the interface returns an R class object, using the success method to encapsulate pageInfo into the response body. R is a general response class that encapsulates information such as data and status of the interface response.
3.4 Functional test
After the code is written, we need to restart the project. After the completion, directly visit the homepage of the management system, and the list page of employee management will be opened by default. We can check whether the list data can be displayed normally, or test the paging function through the paging plug-in, and Fuzzy query function of employee name.
When testing, you can use the browser's monitoring tool to view the data interaction details between the page and the server. And with the help of debug, according to the server parameter reception and logic execution.
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-kgoO7taS-1688460908094)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021805171.png)]
During the test, it can be found that for the employee status field (status), the server returns a status code (1 or 0), but the page displays "normal" or "disabled", because the page is displaying data was processed.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-RQTKX90k-1688460908095)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131541053.png)]
F8 twice
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-XIHfXtYv-1688460908095)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131541021.png)]
3 times F8
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-6kithCUS-1688460908096)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131541653.png)]
F8
==> Preparing: SELECT COUNT(*) FROM employee
==> Parameters:
<== Columns: COUNT(*)
<== Row: 4
<== Total: 1
==> Preparing: SELECT id,username,name,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee ORDER BY update_time DESC LIMIT ?
==> Parameters: 10(Long)
<== Columns: id, username, name, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<== Row: 1665721390604546050, lisi, 李四, e10adc3949ba59abbe56e057f20f883e, 13528659545, 1, 358956221565220, 1, 2023-06-05 22:05:02, 2023-06-05 22:05:02, 1, 1
<== Row: 1665562193044803586, zhangsan, zs, e10adc3949ba59abbe56e057f20f883e, 13412345678, 1, 350689566956852556, 1, 2023-06-05 11:32:26, 2023-06-05 11:32:26, 1, 1
<== Row: 1665561007872905218, zhagsan, 张三, e10adc3949ba59abbe56e057f20f883e, 13412345678, 1, 350689566956852556, 1, 2023-06-05 11:27:44, 2023-06-05 11:27:44, 1, 1
<== Row: 1, admin, 管理员, e10adc3949ba59abbe56e057f20f883e, 13812312312, 1, 110101199001010047, 1, 2021-05-06 17:20:07, 2021-05-10 02:24:09, 1, 1
<== Total: 4
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-hbaplbux-1688460908097)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131541028.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-GTIWVIAb-1688460908097)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131541445.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-Dsma9Jn4-1688460908098)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131542324.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-3aifa4Pi-1688460908099)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131542565.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-pB8Y46cJ-1688460908100)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131542584.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-9PS8Gm5r-1688460908100)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131542621.png)]
4. Enabling/disabling employee accounts
4.1 Demand Analysis
On the employee management list page, you can enable or disable an employee account . Employees whose accounts are disabled cannot log in to the system, and employees whose accounts are enabled can log in normally. If the status of an employee account is normal, the button is displayed as "Disabled", and if the status of the employee account is disabled, the button is displayed as "Enabled".
It should be noted that only the administrator (admin user) can enable and disable other ordinary users, so the enable and disable buttons are not displayed after ordinary users log in to the system.
A. admin administrator login
B. Ordinary user login
4.2 Program Execution Flow
4.2.1 Dynamic display of page buttons
In the above requirements, we mentioned that the effect that needs to be achieved is: only administrators (admin users) can enable and disable other ordinary users, so after ordinary users log in to the system, the enable and disable buttons are not displayed . How is it displayed on the page? So that only the administrator admin can see the enable and disable buttons?
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-QAWJruTQ-1688460908101)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131543430.png)]
1). When the list page (list.html) is loaded, the hook function created is triggered. In the hook function, the user login information will be obtained from localStorage, and then the user name will be obtained
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-wo8yecOq-1688460908101)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131543117.png)]
After getting it, give the model data user
After getting the model data user, judge through the Vue command v-if. If the logged-in user is admin, the enable/disable button will be displayed, otherwise it will not be displayed.
</el-button>
<el-button
type="text"
size="small"
class="delBut non"
@click="statusHandle(scope.row)"
v-if="user === 'admin'" // 通过Vue指令v-if进行判断,如果登录用户为admin将展示 启用/禁用 按钮, 否则不展示
>
{
{ scope.row.status == '1' ? '禁用' : '启用' }}
</el-button>
2). In the page, judge through the Vue command v-if, if the login user is admin, the enable/disable button will be displayed, otherwise it will not be displayed
4.2.2 Execution Process Analysis
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-6RBMtaOu-1688460908102)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131543885.png)]
1. The page sends an ajax request and submits the parameters (id, status) to the server
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-SLdGYm2y-1688460908102)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131543443.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-TASciZ0C-1688460908103)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131543717.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-rdDZUSZ8-1688460908103)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131544148.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-wkob9QrV-1688460908103)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131544276.png)]
2. The server Controller receives the data submitted by the page and calls the Service to update the data
3. Service calls Mapper to operate the database
Why clicking the disable or enable button makes a request
1). When the administrator admin clicks the "Enable" or "Disable" button, the method statusHandle is called
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-mUTubERS-1688460908104)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131544669.png)]
scope.row : get the data information of this row;
At the same time, scope.row will be sent out. scope.row is the fully encapsulated JSON object of the data we see.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-pt04BjlQ-1688460908104)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131544852.png)]
2). In the statusHandle method, make a second confirmation, then initiate an ajax request, and pass the id and status parameters
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-QBSqRSyF-1688460908105)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131544876.png)]
//状态修改
statusHandle (row) {
this.id = row.id //获得id的值
this.status = row.status //获得状态的值
this.$confirm('确认调整该账号的状态?', '提示', {
'confirmButtonText': '确定',
'cancelButtonText': '取消',
'type': 'warning'
}).then(() => {
enableOrDisableEmployee({ 'id': this.id, 'status': !this.status ? 1 : 0 }).then(res => {
console.log('enableOrDisableEmployee',res)
if (String(res.code) === '1') {
this.$message.success('账号状态更改成功!')
this.handleQuery()
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
})
},
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-N3jZsQaM-1688460908105)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131545498.png)]
// 修改---启用禁用接口
function enableOrDisableEmployee (params) {
return $axios({
url: '/employee',
method: 'put',
data: { ...params }
})
}
Finally, an asynchronous request is initiated to request the server, and the request information is as follows:
ask | illustrate |
---|---|
request method | PUT |
request path | /employee |
request parameters | {“id”:xxx,“status”:xxx} |
{…params} : Three dots is the spread operator that appeared in ES6. The function is to traverse all the properties that the currently used object can access, and put the properties into the current object.
4.3 Code implementation
Before developing the code, you need to sort out the execution process of the entire program:
1). The page sends an ajax request and submits the parameters (id, status) to the server
2). The server Controller receives the data submitted by the page and calls the Service to update the data
3). Service calls Mapper to operate the database
/**
* 根据id修改员工信息
* @param employee
* @return
*/
@PutMapping
public R<String> update(@RequestBody Employee employee){
log.info(employee.toString());
return null;
}
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-FNxCuOsq-1688460908106)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131545374.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ZHK4wg1i-1688460908106)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131550246.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-tiOF9DeG-1688460908107)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131550257.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-oms8Xy8O-1688460908107)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131550686.png)]
Enabling and disabling employee accounts is essentially an update operation, that is, an operation on the status field. Create an update method in the Controller, which is a general method for modifying employee information.
/**
* 根据id修改员工信息
* @param employee
* @return
*/
@PutMapping
public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
log.info(employee.toString());
Long empId = (Long)request.getSession().getAttribute("employee");
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser(empId);
employeeService.updateById(employee);
return R.success("员工信息修改成功");
}
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-BYsdqUYa-1688460908108)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131550918.png)]
code explanation 1
The above code is a controller method in the Java Spring Boot framework. The code uses @PutMapping
annotations to indicate that this method handles HTTP PUT requests.
request.getSession().getAttribute("employee")
The purpose of the method is to modify the employee information based on the provided employee id (via get). The parameters of the method include HttpServletRequest
object and Employee
object, where HttpServletRequest
the object is used to obtain the employee ID in the current session, and Employee
the object contains the employee information that needs to be updated.
The execution steps of the code are as follows:
- First, the logger
log
prints outemployee
a string representation of the object so that incoming employee information can be viewed in the log. - By
request.getSession().getAttribute("employee")
getting the employee ID in the current session, and assigning it toempId
a variable. - Use to
LocalDateTime.now()
get the current time and set it as the update time for employee information. - Will
empId
be set as the update user for employee information. - Call
employeeService.updateById(employee)
the method to update the employee information corresponding to the employee ID in the database. - Finally, a successful
R
object is returned, which contains a message string "Employee information modified successfully".
It should be noted that the representation in the code R<String>
returns an object containing the generic String
as R
. R
It may be a custom response object, which contains some fields used to represent the result of the request, such as status code, message, etc. For specific implementation, you may need to check the relevant code in the project.
in detail
The above code is a controller method in the Java Spring Boot framework. The code uses @PutMapping
annotations to indicate that this method handles HTTP PUT requests.
request.getSession().getAttribute("employee")
The purpose of the method is to modify the employee information based on the provided employee id (via get). The parameters of the method include HttpServletRequest
object and Employee
object, where HttpServletRequest
the object is used to obtain the employee ID in the current session, and Employee
the object contains the employee information that needs to be updated.
The execution steps of the code are as follows:
- First, the logger
log
prints outemployee
a string representation of the object so that incoming employee information can be viewed in the log. - By
request.getSession().getAttribute("employee")
getting the employee ID in the current session, and assigning it toempId
a variable. - Use to
LocalDateTime.now()
get the current time and set it as the update time for employee information. - Will
empId
be set as the update user for employee information. - Call
employeeService.updateById(employee)
the method to update the employee information corresponding to the employee ID in the database. - Finally, a successful
R
object is returned, which contains a message string "Employee information modified successfully".
It should be noted that the representation in the code R<String>
returns an object containing the generic String
as R
. R
It may be a custom response object, which contains some fields used to represent the result of the request, such as status code, message, etc. For specific implementation, you may need to check the relevant code in the project.
do not understand the point
There are two parameters of the method: HttpServletRequest object and Employee object. The HttpServletRequest object is used to obtain the employee ID in the current session, and the Employee object contains the employee information that needs to be updated.
I'm very sorry, maybe that part of my explanation wasn't clear enough. I will re-explain the parameters of the method and what they do.
-
HttpServletRequest object: HttpServletRequest is a class in Java Servlet, which represents the HTTP request issued by the client. In this method, we pass in the HttpServletRequest object as a parameter to get the employee ID in the current session.
The current session refers to the information about the client kept by the server during the interaction with the client (usually a web browser). Sessions can span multiple HTTP requests and remain active for the duration of the session. Through the HttpServletRequest object, we can obtain information related to the session, such as the attribute value stored in the session.
In this code, we use
request.getSession().getAttribute("employee")
to get the value of an attribute named "employee" in the session. The attribute value should be the ID of the currently logged in employee. -
Employee object: Employee is a custom class that represents employee information. In this method, we pass the Employee object as a parameter, which contains the employee information that needs to be updated.
Employee objects typically have multiple attributes such as name, title, salary, and so on. In this code, the Employee object we pass in should contain the employee information that needs to be updated. Through this object, we can get and set various attribute values of employees.
In the subsequent code of the method, we will use the methods of the Employee object to set the employee's update time and update the user, and then pass it to a
updateById
method called to update the employee's information in the database.
Summary: The HttpServletRequest object is used to obtain the employee ID in the current session, and the Employee object contains the employee information that needs to be updated. Through these two parameters, we can obtain the employee ID and updated employee information, and perform corresponding operations, such as recording the update time and updating the user, and then update the database.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-JgNNzjoe-1688460908108)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131550358.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-RLM1JVjA-1688460908109)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131550262.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-DXCcbbtw-1688460908109)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131551383.png)]
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-sL4IpM3U-1688460908110)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131551952.png)]
5 times F8
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-Uci1NjFu-1688460908110)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131551679.png)]
id incorrect update failed
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-5wKFdFBK-1688460908110)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131552765.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-YldLBLMm-1688460908111)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131552126.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-q1Dk3KPi-1688460908111)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131552710.png)]
correct id
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-MUp6sEQQ-1688460908112)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131552901.png)]
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-A0aS3BKK-1688460908112)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131553078.png)]
4.4 Functional test
After the code is written, we need to restart the project. Then visit the front-end page to test "enable" or "disable".
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-Ak6gN6U3-1688460908113)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021806965.png)]
No error was reported during the test, but the function was not implemented, and the data in the database did not change. But from the logs output by the console, it can be seen that the update was not successful.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-xe7AtMoR-1688460908113)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021806475.png)]
In our database table structure, this ID does not exist, and the ID corresponding to Feng Qingyang in the database is 1420038345634918401
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-GTPRcVIU-1688460908113)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021806756.png)]
4.5 Code fixes
4.5.1 Cause Analysis
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-GcJSgHbQ-1688460908114)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021806412.png)]
By observing the SQL output from the console, it is found that the value of the employee id passed on the page is inconsistent with the id value in the database. What is going on?
During pagination query, the server will serialize the returned R object into json format and convert it into data in json format. The ID of the employee is a Long type data, and it is a long integer data with a length of 19 digits. There is no problem with data being returned to the front end.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ptku2prd-1688460908114)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02/202304021806699.png)]
那么具体的问题出现在哪儿呢?
问题实际上, 就出现在前端JS中, js在对长度较长的长整型数据进行处理时, 会损失精度, 从而导致提交的id和数据库中的id不一致。 这里,我们也可以做一个简单的测试,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
alert(1420038345634918401);
</script>
</head>
<body>
</body>
</html>
4.5.2 解决方案
要想解决这个问题,也很简单,我们只需要让js处理的ID数据类型为字符串类型即可, 这样就不会损失精度了。同样, 大家也可以做一个测试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
alert("1420038345634918401");
</script>
</head>
<body>
</body>
</html>
那么在我们的业务中, 我们只需要让分页查询返回的json格式数据库中, long类型的属性, 不直接转换为数字类型, 转换为字符串类型就可以解决这个问题了 , 最终返回的结果为 :
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YZfFYR5I-1688460908114)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02/202304021807347.png)]
4.5.3 代码修复
由于在SpringMVC中, 将Controller方法返回值转换为json对象, 是通过jackson来实现的, 涉及到SpringMVC中的一个消息转换器MappingJackson2HttpMessageConverter, 所以我们要解决这个问题, 就需要对该消息转换器的功能进行拓展。
具体实现步骤:
1). 提供对象转换器JacksonObjectMapper,基于Jackson进行Java对象到json数据的转换(资料中已经提供,直接复制到项目中使用)
2). Extend the message converter of Spring mvc in the WebMvcConfig configuration class, and use the provided object converter in this message converter to convert Java objects to json data
1). Introduce JacksonObjectMapper
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
The custom object converter mainly specifies how to process LocalDateTime, LocalDate, and LocalTime when serializing and deserializing json data, and convert BigInteger and Long type data directly into strings.
2). Override the method extendMessageConverters in WebMvcConfig
/**
* 扩展mvc框架的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器...");
//创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
//设置对象转换器,底层使用Jackson将Java对象转为json
messageConverter.setObjectMapper(new JacksonObjectMapper());
//将上面的消息转换器对象追加到mvc框架的转换器集合中
converters.add(0,messageConverter);
}
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-teHTLONy-1688460908115)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131553415.png)]
test
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-MQ5BLdhK-1688460908115)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131553663.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-HDAo2cCe-1688460908116)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131553038.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-l8pLvPDF-1688460908116)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131553871.png)]
4 times F8
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-PQunt52v-1688460908119)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554063.png)]
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-4ycAP3ya-1688460908119)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554799.png)]
let go
Restart
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-QPWiuaow-1688460908119)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554310.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-BN09ZbqH-1688460908120)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554974.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-mDQQgjAk-1688460908120)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554126.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-R0ztbrd4-1688460908121)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554438.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-m8x4w378-1688460908121)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131554302.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-qYhpXRqz-1688460908122)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131555469.png)]
5. Edit employee information
Before developing the code, it is necessary to sort out the operation process and the execution process of the corresponding program:
1. When the edit button is clicked, the page jumps to add.html, and the parameter [employee id] is carried in the url
2. Get it on the add.html page The parameter [employee id] in the url
3. Send an ajax request, request the server, and submit the employee id parameter at the same time
4. The server receives the request, queries the employee information according to the employee id, and responds to the page with the employee information in the form of json
5. The page receives The json data responded by the server is echoed with the employee information through VUE data binding.
6. Click the save button, send an ajax request, and submit the employee information on the page to the server in json form.
7. The server receives the employee information, and Perform processing, and respond to the page after completion.
8. After receiving the response information from the server, the page performs corresponding processing
Note: the add.html page is a public page, and both adding and editing employees are performed on this page
1. When the edit button is clicked, the page jumps to add.html and carries the parameter [employee id] in the url
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-erMUGilk-1688460908122)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131555057.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-sEcqqWv7-1688460908123)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306142117010.png)]
2. Obtain the parameter [employee id] in the url on the add.html page
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-eSfqYXtW-1688460908123)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131555202.png)]
3. Send an ajax request, request the server, and submit the employee id parameter at the same time
4. The server receives the request, queries the employee information according to the employee id, and responds to the page with the employee information in the form of json
5. The page receives the json data responded by the server, and echoes the employee information through the data binding of VUE
The reported 404 we just saw uses this id as part of the request path
why send request
Because after receiving the request, our server can query the user according to the id and then echo it to the page and respond to the page in the form of JSON
The page receives the json data responded by the server, and echoes the employee information through VUE's data binding
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-KztVmtZU-1688460908124)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131555540.png)]
important point:
There are two interactions with the server during the modification process
Send the request for the first time to query the corresponding data for echo
The second time when we click the save button, submit our modified data to our server
5.1 Requirements Analysis
Click the "Edit" button on the employee management list page to jump to the edit page, echo the employee information on the edit page and modify it, and finally click the "Save" button to complete the edit operation.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-pwxDABQA-1688460908124)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021807123.png)]
Then from the above analysis, we can see that the editing function currently implemented, we need to implement two methods:
A. Query based on ID, used for page data echo
B. Save changes
Execution Process (Video Version)
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-8b9eh6MQ-1688460908125)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131555348.png)]
[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-XNx1qGS7-1688460908125)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131555106.png)]
5.2 Program Execution Flow
Before developing the code, you need to sort out the operation process and the execution process of the corresponding program:
1). When the edit button is clicked, the page jumps to add.html and carries the parameter [employee id] in the url
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-Ov7g9NOn-1688460908126)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021807323.png)]
2). Get the parameter [employee id] in the url on the add.html page
3). Send an ajax request, request the server, and submit the employee id parameter at the same time
4). The server receives the request, queries the employee information according to the employee id, and responds the employee information to the page in the form of json
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-0BULTI6z-1688460908126)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202304021807595.png)]
5). The page receives the json data responded by the server, and echoes the employee information through the data binding of VUE
6). Click the save button, send an ajax request, and submit the employee information on the page to the server in json format
7). The server receives employee information, processes it, and responds to the page after completion
8). After receiving the response information from the server, the page performs corresponding processing
Note: the add.html page is a public page, and both adding and editing employees are performed on this page
5.3 Code implementation
5.3.1 Query by ID
After the above analysis, we can see that when querying employee information based on ID, the requested information is as follows:
ask | illustrate |
---|---|
request method | GET |
request path | /employee/{id} |
Code:
Add a method in EmployeeController to query employee information based on ID.
/**
* 根据id查询员工信息
* @param id
* @return
*/
@GetMapping("/{id}")
public R<Employee> getById(@PathVariable Long id){
log.info("根据id查询员工信息...");
Employee employee = employeeService.getById(id);
if(employee != null){
return R.success(employee);
}
return R.error("没有查询到对应员工信息");
}
code explanation
Explanation 1
The above code is a Java code fragment based on the Spring framework, which is used to implement a RESTful API interface. The code contains a GET request method for querying employee information based on employee ID.
The explanation is as follows:
@GetMapping("/{id}")
: This is an annotation that specifies the URL path of the HTTP GET request./{id}
Indicates that the path needs to contain a path parameter named id.public R<Employee> getById(@PathVariable Long id)
: This is a public method with return type R. R is a custom response object used to encapsulate the return result of the API interface. The method is named getById and receives a path parameter named id.log.info("根据id查询员工信息...")
: This is a log output statement, which is used to record a message in the log, indicating that the operation of querying employee information based on employee ID is being performed.Employee employee = employeeService.getById(id)
: This is to call the getById method of a service object named employeeService, and pass in the id parameter to query employee information based on employee ID. The query result will be saved in the employee object.if(employee != null)
: If the employee information is queried (employee is not null), execute the next line of code; otherwise, execute the logic that returns an error message.return R.success(employee)
: If the employee information is queried, use the employee information as the data of the successful response, use the R.success method to encapsulate the response result, and then return.return R.error("没有查询到对应员工信息")
: If no employee information is found, use the error information as the data of the error response, use the R.error method to encapsulate the response result, and then return.
In general, this code implements a GET request interface, which queries the corresponding employee information by passing in the employee ID, and returns the query result after being encapsulated in a custom response object R.
Explanation 2
When the client sends a GET request to the specified URL path (for example: /{id}
), this method will be executed. In this URL path, we expect to include a path parameter named id in order to specify the ID of the employee being queried.
Inside the method body, first record the operation being executed through the log output, that is, query the employee information according to the employee ID.
Then, obtain the corresponding employee information by calling the getById method of a service object named employeeService and using the incoming id parameter as the query condition. The query results will be saved in an object named employee.
Next, judge whether the employee information is successfully queried by judging whether the employee object is null. If employee is not null, it means that the query is successful, and the employee information is used as the successful response data. The code uses the R.success method to encapsulate the response result into a successful response object R and return it to the client.
If employee is null, it means that no corresponding employee information has been queried. The code uses the R.error method to encapsulate the error information into an error response object R and return it to the client.
In short, this code fragment implements a GET request interface, and the client queries the corresponding employee information by passing the employee ID. If the query is successful, return a successful response containing employee information; if the query fails, return an error response containing error information.
Explain in detail Employee employee = employeeService.getById(id); This is not very clear, can you explain it in detail
When the code reaches Employee employee = employeeService.getById(id);
this line, it calls the method employeeService
of the service object named getById
, passing id
the parameters.
In the code, employeeService
it is a service object that encapsulates employee-related operations. By calling the method, it will query the corresponding employee information getById
according to the parameters passed in .id
The methods here getById
may include database query operations or other data acquisition logic, and the specific implementation depends on the employeeService
specific implementation of the object. It will query the database or other data sources according to the parameters passed in id
to obtain the corresponding id
employee information.
The query results will be stored in an object employee
named Employee
. This object will contain the queried employee information such as name, position, salary, etc.
Finally, employee
the object will be used for subsequent judgment and processing. According to the query result, the code will decide to return a successful response (containing employee
the object as the response data) or return an error response (indicating that the corresponding employee information is not queried).
All in all, Employee employee = employeeService.getById(id);
the function of this line of code is to call the method of the service object to obtain the corresponding id
employee information, and store the query result in employee
the object named for subsequent processing and returning a response.
employeeService
is a service object that handles employee information. getById
The method is a function in the service object, and its function is to obtain the corresponding employee information according to the incoming employee ID.
In the code, through employeeService.getById(id)
this line, the program will call getById
the method and pass it in id
as a parameter. This way, getById
the method knows which employee to query for information.
getById
id
The method will look up the corresponding employee information in the database or other data sources according to the provided . The result of the query will be assigned to a employee
variable called , which is an Employee
object of type.
Finally, depending on the condition of the query results, the code decides to return a success response or an error response. If the employee information is successfully found, employee
the data is returned as a successful response. If no corresponding employee information is found, an error message will be returned.
employeeService
To put it simply, the purpose of this code is to obtain the information of the corresponding employee by calling the method according to the incoming employee ID getById
, and return the corresponding response according to the query result.
Employee employee = employeeService.getById(id);
Represents an object instance for obtaining employee information.
employeeService
It is a dependency injected Bean, which implements EmployeeService
the interface, which defines getById
the method, the method's parameters are id
, and the return value is Employee
the object.
getById
id
The implementation of the method is to obtain the object instance of the employee information by calling the field of the employee information stored in the database . If the employee information in the database id
matches the value passed in, return the object instance of the employee information, otherwise return null
.
Since this interface is defined as a RESTful API, the returned employee information object instance should follow the HTTP response status code and response header specifications. Typically, the response status code is 200 (success) or 404 (resource not found).
In the above code, if the employee information is not empty, a response object is returned R.success(employee)
, indicating that the employee information has been successfully queried; otherwise, an error response is returned R.error("没有查询到对应员工信息")
, indicating that the employee information cannot be queried.
test
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-4LVFSx7e-1688460908127)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131556298.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-pbVuRtMA-1688460908127)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131557745.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-yhWf808k-1688460908127)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131557489.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ULIpWPwr-1688460908128)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131557465.png)]
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-vyjNO7Bc-1688460908128)(https://cdn.jsdelivr.net/gh/zyziga/picodemo/takeaway/day02 /202306131557210.png)]
5.3.2 Modify Employee
After the above analysis, we can see that when modifying employee information, the requested information is as follows:
ask | illustrate |
---|---|
request method | PUT |
request path | /employee |
request parameters | {…} json format data |
Code:
Add a method in EmployeeController to update employee information based on ID.
/**
* 根据id修改员工信息
* @param employee
* @return
*/
@PutMapping
public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
log.info(employee.toString());
Long empId = (Long)request.getSession().getAttribute("employee");
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser(empId);
employeeService.updateById(employee);
return R.success("员工信息修改成功");
}
5.4 Functional test
After the code is written, we need to restart the project. Then visit the front-end page and test according to the operation process analyzed above to check whether the data is modified normally.