[SpringMVC from entry to actual combat tutorial] Chapter 5 SpringMVC JSON data interaction

Five, SpringMVC JSON data interaction

5.1 Synchronous and asynchronous review

insert image description here

5.1.1 Synchronous requests

  • When the browser sends a synchronization request to the server, the browser will be in a waiting state while the service is processing the synchronization request, and the subsequent operations can only be performed after receiving the response from the server.
  • After the server processes the request, it responds the data to the browser and overwrites the original data in the browser's memory . The browser - reloads the page (performs redirection or request forwarding) and displays the data responded by the server .
//1、客户端浏览器发送用户的登录请求
登录表单 -> 点击submit按钮

//2、需要等待响应,才能执行后续操作
//...

5.1.2 Asynchronous requests

  • When the browser sends an asynchronous request to the server, the browser can perform subsequent operations without waiting for the server's response while the service is processing the asynchronous request.
  • After the server processes the request response string data to the browser , the browser— without loading the page (no more redirection or request forwarding), can implement partial changes to the page .
//1、注册表单的用户名的校验,用户填写完用户名就发送异步请求
$.ajax({
    
    
    url:"userNameUnique.do",
    data:{
    
    
        userName: $("#userName").val()
    },
    success:function(){
    
    
        //请求成功的回调函数
    }
})

//2、ajax方法执行之后,无需等待回调执行,可以继续执行后续js代码

The principle of asynchronous request:

	浏览器把请求交给代理对象—XMLHttpRequest(绝大多数浏览器都内置了这个对象),由代理对象向服务器发起请求,接收、解析服务器响应的数据,并把数据更新到浏览器指定的控件上。从而实现了页面数据的局部刷新。

insert image description here

5.2 Ajax and JSON review

5.2.1 Ajax

	Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
	
	通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

jQuery.ajax(url,[settings]):

	通过 HTTP 请求加载远程数据。

	jQuery 底层 AJAX 实现。简单易用的高层实现见 `$.get`, `$.post` 等。`$.ajax()` 返回其创建的 XMLHttpRequest 对象。大多数情况下你无需直接操作该函数,除非你需要操作不常用的选项,以获得更多的灵活性。

parameter:

    url: 一个用来包含发送请求的URL字符串。

    settings: AJAX 请求设置。所有选项都是可选的。

Settings common options:

parameter name Parameter Type describe
async Boolean (Default: true) By default, all requests are asynchronous. Set this option to false if you need to send synchronous requests. Note that the synchronous request will lock the browser, and other operations of the user must wait for the request to be completed before they can be executed.
contentType String (Default: "application/x-www-form-urlencoded") The content encoding type when sending messages to the server. The default is suitable for most cases. If you explicitly pass a content-type to $.ajax() then it must be sent to the server (even if there is no data to send)
data Object,String Data sent to the server. Will be automatically converted to request string format. GET requests will be appended to the URL. See the processData option description to disable this automatic conversion. Must be in Key/Value format. If it is an array, jQuery will automatically assign the same name to different values. For example, {foo:[“bar1”, “bar2”]} translates to “&foo=bar1&foo=bar2”.
dataType String The expected data type returned by the server. If not specified, jQuery will automatically judge intelligently based on the MIME information of the HTTP package, for example, the XML MIME type is recognized as XML. In 1.4, JSON will generate a JavaScript object, and script will execute the script. Then the data returned by the server will be parsed according to this value and passed to the callback function
error Function (Default: Automatically judge (xml or html)) This function is called when the request fails. There are three parameters: XMLHttpRequest object, error message, (optional) caught exception object. If an error occurs, the error message (second parameter) may be "timeout", "error", "notmodified" and "parsererror" in addition to getting null.
headers map Default: {}, an additional "{key:value}" pair map to send with the request. This setting is set before the beforeSend function is called; therefore, the value set in the message header can override any setting within the scope of the beforeSend function.
timeout Number Set the request timeout in milliseconds. This setting overrides the global setting.
type String (Default: "GET") Request method ("POST" or "GET"), default is "GET". Note: Other HTTP request methods such as PUT and DELETE can also be used, but only supported by some browsers.
url String (default: current page address) The address to send the request to.

5.2.2 JSON

  • JSON (JavaScript Object Notation, JS Object Notation) is a lightweight data exchange format;
  • Based on a subset of ECMAScript, it uses a text format that is completely independent of the programming language to store and represent data;
  • Conciseness and clear hierarchy make JSON an ideal data exchange language;
  • It is easy for people to read and write, but also easy for machines to parse and generate, and effectively improves the efficiency of network transmission;

index.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>首页</h1>
        <a href="views/json.jsp">JSON</a><br>
        <a href="views/request.jsp">请求</a><br>
        <a href="views/response.jsp">响应</a><br>
    </div>
</body>
</html>

json.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <script type="text/javascript">
        //JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
        //这是一个对象,注意键名也是可以使用引号包裹的
        var obj = {
      
      
            name: 'tom',
            age: 20
        };
        
        //这是一个 JSON 字符串,本质是一个字符串
        var json = '{"name": "jerry", "age": 19}';

        //JSON字符串转换为JS对象,使用JSON.parse()方法:
        var obj2 = JSON.parse(json);

        //JS对象转换为JSON字符串,使用JSON.stringify()方法:
        var json2 = JSON.stringify(obj);
    </script>
</head>
<body>
</body>
</html>

5.3 SpringMVC handles asynchronous requests

	为实现浏览器与控制器类之间的 JSON 数据交互,Spring MVC 提供了 MappingJackson2HttpMessageConverter 实现类默认处理 JSON 格式请求响应。该实现类利用 Jackson 开源包读写 JSON 数据,将 Java 对象转换为 JSON 对象和 XML 文档,同时也可以将 JSON 对象和 XML 文档转换为 Java 对象。

5.3.1 Request

  • The client requests the key/value value, the contentType is the default value of application/x-www-form-urlencoded, and the server can obtain the data without processing.
  • The client request is a json string, the contentType needs to be specified as application/json, and the @RequestBody annotation needs to be used on the server side to convert the json string into a java object .

5.3.2 Response

  • You need to use the @ResponseBody annotation to convert java objects into json strings for output .

5.4 Implementation process

5.4.1 Import jackson package

	Jackson 是最流行的 json 解析器之一。Spring MVC 的默认 json 解析器便是 Jackson。
	
	Jackson 优点很多。Jackson 所依赖的 jar 包较少,简单易用。与其他 Java 的 json 的框架 Gson 等相比,Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。
	
	Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,当升级到 2.x 版本时,包名变为 com.fasterxml.jackson。
	
	三个核心模块:
		jackson-core: 核心包。定义了低级的流式API,包括了JSON处理细节。
        jackson-annotations: 注解包。包含了Jackson的注解。
        jackson-databind: 数据绑定包。实现了对象和JSON之间的转换,这个包依赖上面两个包。

	Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。
        
	其他优秀的json解析工具:Google的Gson、阿里巴巴的FastJson等。

Method 1: Import jar package

insert image description here

Method 2: maven dependency configuration

<dependencies>
    <!-- spring核心包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springbean包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springcontext包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- spring表达式包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springAOP包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springAspects包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- spring对web的支持 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springwebMVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>

    <!-- 配置javaweb环境 -->
    <!-- servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- jstl -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <!-- jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.5</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.5</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.5</version>
    </dependency>
</dependencies>

Note: spring4.x must use jackson2.x version, while spring3.x version uses jackson1.x version.

5.4.2 Configuration

Configure the json converter in the processor adapter:

<!--在处理器适配器中配置json转换器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json;charset=UTF-8</value>
                        <value>text/html;charset=UTF-8</value>
                        <value>text/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </list>
    </property>
</bean>

Note: If you use <mvc:annotation-driven/>it, you don't need to define the above content.

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- springmvc的注解式开发 -->
    <!-- 开启组件扫描 -->
    <context:component-scan base-package="com.newcapec.controller"/>

    <!-- MVC注解驱动 -->
    <mvc:annotation-driven/>

    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置视图地址的前缀和后缀:简化视图地址 -->
        <property name="prefix" value="/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

5.4.3 POJO

Dept.java:

public class Dept {
    
    
    
    private Integer deptno;
    private String dname;

    public Integer getDeptno() {
    
    
        return deptno;
    }

    public void setDeptno(Integer deptno) {
    
    
        this.deptno = deptno;
    }

    public String getDname() {
    
    
        return dname;
    }

    public void setDname(String dname) {
    
    
        this.dname = dname;
    }

    @Override
    public String toString() {
    
    
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                '}';
    }
}

Emp.java:

public class Emp {
    
    

    private Integer empno;
    private String ename;
    private String job;
    private Double sal;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date hiredate;
    private Dept dept;

    public Integer getEmpno() {
    
    
        return empno;
    }

    public void setEmpno(Integer empno) {
    
    
        this.empno = empno;
    }

    public String getEname() {
    
    
        return ename;
    }

    public void setEname(String ename) {
    
    
        this.ename = ename;
    }

    public String getJob() {
    
    
        return job;
    }

    public void setJob(String job) {
    
    
        this.job = job;
    }

    public Double getSal() {
    
    
        return sal;
    }

    public void setSal(Double sal) {
    
    
        this.sal = sal;
    }

    public Date getHiredate() {
    
    
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
    
    
        this.hiredate = hiredate;
    }

    public Dept getDept() {
    
    
        return dept;
    }

    public void setDept(Dept dept) {
    
    
        this.dept = dept;
    }

    @Override
    public String toString() {
    
    
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", sal=" + sal +
                ", hiredate=" + hiredate +
                ", dept=" + dept +
                '}';
    }
}

5.4.4 Request key/value

request.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
    <script type="text/javascript">
        //key-value值
        function sendKeyValue() {
      
      
            //js的字面量对象
            var emp = {
      
      
                empno: 1001,
                ename: 'tom',
                job: 'staff',
                sal: 4500,
                hiredate: '2022-01-09',
                'dept.deptno': 10,
                'dept.dname': 'HR'
            };
            
            //发送异步请求
            $.ajax('sendKeyValue.do', {
      
      
                type: 'post',
                data: emp,
                //内容类型:将数据转换为keyValue向服务器提交
                contentType: 'application/x-www-form-urlencoded',
                success: function (resp) {
      
      
                    alert(resp);
                }
            });
        }
    </script>
</head>
<body>
<div style="text-align: center">
    <p><a href="javascript:sendKeyValue()">向服务器端发送key/value值</a></p>
    <p><a href="javascript:sendJson()">向服务器端发送json值</a></p>
</div>
</body>
</html>

Controller:

@Controller
public class JsonController {
    
    

    @RequestMapping("sendKeyValue.do")
    public void sendKeyValue(Emp emp, HttpServletResponse response) throws IOException {
    
    
        System.out.println("请求数据:" + emp);
        response.getWriter().write("success");
    }
}

Request content type:

insert image description here

Request data:

insert image description here

Request data source:

insert image description here

5.4.5 request json string

request.jsp page js:

//json字符串格式
function sendJson() {
    
    
    //js的字面量对象
    var emp = {
    
    
        empno: 1002,
        ename: 'jerry',
        job: 'manager',
        sal: 6800,
        hiredate: '2022-01-09',
        //区别于key/value的写法
        dept: {
    
    
            deptno: 20,
            dname: 'SALE'
        }
    };
    
    //发送异步请求
    $.ajax('sendJson.do', {
    
    
        type: 'post',
        data: JSON.stringify(emp),
        //内容类型:告知服务器提交数据为json字符串
        contentType: 'application/json',
        success: function (resp) {
    
    
            alert(resp);
        }
    });
}

Controller:

@Controller
public class JsonController {
    
    

    /**
     * @RequestBody
     * 位置:形参
     * 作用:将前端提交的json字符串,转换为Java对象
     */
    @RequestMapping("/sendJson.do")
    public void sendJson(@RequestBody Emp emp, HttpServletResponse response) throws IOException {
    
    
        System.out.println("请求数据:" + emp);
        response.getWriter().write("success");
    }
}

Request content type:

insert image description here

Request data:

insert image description here

Request data source:

insert image description here

5.4.6 Response single data string

response.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
    <script type="text/javascript">
        function responseString() {
            $.ajax('responseString.do', {
                type: 'get',
                success: function (resp) {
                    alert(resp);
                }
            });
        }
    </script>
</head>
<body>
<div style="text-align: center">
    <p><a href="javascript:responseString()">获取普通字符串数据</a></p>
    <p><a href="javascript:responseObject()">获取对象数据</a></p>
    <p><a href="javascript:responseList()">获取批量数据</a></p>
    <div id="data">
    </div>
    <table border="1" width="500" align="center">
        <thead>
        <tr>
            <th>员工编号</th>
            <th>员工姓名</th>
            <th>员工岗位</th>
            <th>员工薪资</th>
            <th>入职日期</th>
        </tr>
        </thead>
        <tbody id="tab"></tbody>
    </table>
</div>
</body>
</html>

Controller:

@Controller
public class JsonController {
    
    

    /*
     * @ResponseBody
     * 位置:方法和类
     * 作用:将当前方法的返回值以json字符串的形式响应到前端
     *      即使返回值为String类型,也不再进行页面跳转(返回值不再是视图名),就是需要响应的数据
     */
    @ResponseBody
    @RequestMapping("responseString.do")
    public String responseString(){
    
    
        return "success";
    }
}

5.4.7 Response json object string

response.jsp page js:

function responseObject() {
    
    
    $.ajax('responseObject.do', {
    
    
        type: 'get',
        success: function(resp) {
    
    
            //在回调函数的参数中直接获取是js的字面对象
            // alert(resp);
            //jquery中的ajax方法,在接收到后台响应的json字符串时,会自动进行json->object的转换
            var str = '<p>员工编号:' + resp.empno + '</p>';
            str += '<p>员工姓名:' + resp.ename + '</p>';
            str += '<p>员工岗位:' + resp.job + '</p>';
            str += '<p>员工薪资:' + resp.sal + '</p>';
            str += '<p>入职日期:' + resp.hiredate + '</p>';
            $('#data').html(str);
        }
    });
}

Controller:

@Controller
public class JsonController {
    
    

    /**
     * 响应json数据
     * 响应单个数据(一个实体对象)
     *
     * @ResponseBody
     * 位置:方法,返回值
     * 作用:将该方法的返回值转换为json字符串向客户端响应
     */
    @ResponseBody
    @RequestMapping("/responseObject.do")
    public Emp responseObject(){
    
    
        //模拟数据库中的查询
        Emp emp = new Emp();
        emp.setEmpno(201);
        emp.setEname("chris");
        emp.setJob("manager");
        emp.setHiredate(new Date());
        emp.setSal(6300.0);
        //在同步请求中,将数据存放在域对象中...
        //异步请求:直接返回对象
        return emp;
    }
}

Test Results:

insert image description here

5.4.8 Response json array string

response.jsp page js:

function responseList() {
    
    
    $.ajax('responseList.do', {
    
    
        type: 'get',
        success: function(resp) {
    
    
            //在回调函数的参数中直接获取是js的字面对象数组
            var str = '';
            for(var i in resp) {
    
    
                var emp = resp[i];
                str += '<tr>';
                str += '<td>' + emp.empno + '</td>';
                str += '<td>' + emp.ename + '</td>';
                str += '<td>' + emp.job + '</td>';
                str += '<td>' + emp.sal + '</td>';
                str += '<td>' + emp.hiredate + '</td>';
                str += '</tr>';
            }
            $('#tab').html(str);
        }
    });
}

Controller method:

@Controller
public class JsonController {
    
    

    /**
     * 响应json数据
     * 响应批量数据(一个集合,集合中存放的是多个实体对象)
     *
     * @ResponseBody
     * 位置:方法,返回值
     * 作用:将该方法的返回值转换为json字符串向客户端响应
     */
    @ResponseBody
    @RequestMapping("/responseList.do")
    public List<Emp> responseList(){
    
    
        //模拟数据库中的查询
        Emp emp1 = new Emp();
        emp1.setEmpno(201);
        emp1.setEname("chris");
        emp1.setJob("manager");
        emp1.setHiredate(new Date());
        emp1.setSal(6300.0);
        
        Emp emp2 = new Emp();
        emp2.setEmpno(202);
        emp2.setEname("tom");
        emp2.setJob("manager");
        emp2.setHiredate(new Date());
        emp2.setSal(6300.0);
        
        Emp emp3 = new Emp();
        emp3.setEmpno(203);
        emp3.setEname("cherry");
        emp3.setJob("manager");
        emp3.setHiredate(new Date());
        emp3.setSal(6300.0);
        
        List<Emp> list = new ArrayList<>();
        list.add(emp1);
        list.add(emp2);
        list.add(emp3);
        //在同步请求中,将数据存放在域对象中...
        //异步请求:直接返回对象
        return list;
    }
}

Test Results:

insert image description here

5.4.9 Date type processing

There are attributes of date type in the POJO class, just add the @JsonFormat annotation to the attribute:

public class Emp {
    
    

    private Integer empno;
    private String ename;
    private String job;
    private Double sal;
    /**
     * @DateTimeFormat 将客户端提交的字符串转换为Date类型
     * @JsonFormat 将日期类型转换为指定格式字符串
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date hiredate;
    private Dept dept;

    public Integer getEmpno() {
    
    
        return empno;
    }

    public void setEmpno(Integer empno) {
    
    
        this.empno = empno;
    }

    public String getEname() {
    
    
        return ename;
    }

    public void setEname(String ename) {
    
    
        this.ename = ename;
    }

    public String getJob() {
    
    
        return job;
    }

    public void setJob(String job) {
    
    
        this.job = job;
    }

    public Double getSal() {
    
    
        return sal;
    }

    public void setSal(Double sal) {
    
    
        this.sal = sal;
    }

    public Date getHiredate() {
    
    
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
    
    
        this.hiredate = hiredate;
    }

    public Dept getDept() {
    
    
        return dept;
    }

    public void setDept(Dept dept) {
    
    
        this.dept = dept;
    }

    @Override
    public String toString() {
    
    
        return "Emp{" +
            "empno=" + empno +
            ", ename='" + ename + '\'' +
            ", job='" + job + '\'' +
            ", sal=" + sal +
            ", hiredate=" + hiredate +
            ", dept=" + dept +
            '}';
    }
}
public String getJob() {
    return job;
}

public void setJob(String job) {
    this.job = job;
}

public Double getSal() {
    return sal;
}

public void setSal(Double sal) {
    this.sal = sal;
}

public Date getHiredate() {
    return hiredate;
}

public void setHiredate(Date hiredate) {
    this.hiredate = hiredate;
}

public Dept getDept() {
    return dept;
}

public void setDept(Dept dept) {
    this.dept = dept;
}

@Override
public String toString() {
    return "Emp{" +
        "empno=" + empno +
        ", ename='" + ename + '\'' +
        ", job='" + job + '\'' +
        ", sal=" + sal +
        ", hiredate=" + hiredate +
        ", dept=" + dept +
        '}';
}

}

Guess you like

Origin blog.csdn.net/ligonglanyuan/article/details/125318473