SSM + VUE realize simple CRUD

I. project analysis

1, demand

(1) using ssm + vue to implement a crud (database addition, deletion, modification and query).
(2) front and back ends are separated, front page display + background management.

 

2. Technical points

(1) basic framework: SSM (Spring, Spring MVC, Mybatis)
(2) database: Mysql
(3) front end: UI frame iView + vue
(4) project dependency management: maven
(5) paging: pagehelper
(6) reverse engineering: Mybatis Generator
(7) development tools: IDEA + Chrome + HBuilder X

 

II. Project address and screenshot

1. Project address

  front: https://github.com/lyh-man/ssm_crud-front.git

  back: https://github.com/lyh-man/ssm_crud-back.git

2. Project screenshot

(1) initial interface (data query)

Step 1: initialization interface (get the data on the first page)

 

 

 

Step 2: you can set the number of pieces of data per page, as follows: set 20 pieces / page

 

 

 

Step 3: click the setting button to set the table style.

 

 

 

 

 

Step 4: switch the page and refresh the data (send a request to the background according to the current page number to get the data)

 

 

 

(2) modify data

Step 1: click the Edit button (below, select the first data to display the selected data.)

 

 

Step 2: modify data

 

 

Step 3: display data after modification

 

 

 

(3) delete data

Step 1: click the delete button (such as the first data) and a prompt box will pop up

 

 

Step 2: select Ok to delete the data

 

 

 

(3) add data

Step 1: click the Add button

 

 

Step 2: fill in the information

 

 

Step 3: click OK, insert data and jump to the last page

 

 

 

 

III. back end project environment construction

The whole file structure after construction:

 

 

 

1. Use IDEA to create a maven project.

Please refer to https://www.cnblogs.com/l-y-h/p/11454933.html

2. Introduce the jar package (configuration dependency information) that the project depends on.

You need to configure Spring, Spring MVC, mybatis, database connection pool, database driver package, and other jar packages, such as junit.

[pom.xml]

<?
xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lyh</groupId> <artifactId>crud</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>crud Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <jar.version>4.3.17.RELEASE</jar.version> </properties> <dependencies> <!-- Spring WebMVC --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${jar.version}</version> </dependency> <!-- Spring JDBC --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${jar.version}</version> </dependency> <!-- Spring Aspects --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${jar.version}</version> </dependency> <!-- Mybatis --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!-- spring And mybatis Integration package --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <!-- Database connection pool, c3p0 --> <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.4</version> </dependency> <!-- mysql Driving package --> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <!-- jstl --> <!-- https://mvnrepository.com/artifact/jstl/jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- servlet-api --> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- junit --> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- Dependent information for reverse engineering --> <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.5</version> </dependency> <!-- Spring test --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${jar.version}</version> <scope>test</scope> </dependency> <!-- Json --> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.0</version> </dependency> <!-- pagehelper Paging plugins --> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.0.0</version> </dependency> </dependencies> <build> <finalName>crud</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>

 

3. Configure the file of ssm integration (the detailed process will be expanded later).

  web.xml,spring,springmvc,mybatis.

4. Official documents:

  Spring:http://spring.io/docs

  MyBatis:http://mybatis.github.io/mybatis-3/

Use of paging component: https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/en/HowToUse.md

 

3. (3.1) basic configuration of SSM -- configuration web.xml

1. Configure Spring container

The read location used to get the Spring configuration file (applicationContext.xml).
< context param > is directly configured in the < web app > tag of web.xml, which belongs to the context parameter and can be used in the whole web application. It is global, so it is stored in the servletContext object (that is, the application object). It can be obtained by getServletContext().getInitParameter("contextParam").

[stay web.xml Configuration]

<!-- step1: Configure global parameters, start Spring container -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <!-- If no value is provided, the default is to find/WEB-INF/applicationContext.xml.  -->
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 

2. Configure the front-end controller of spring MVC

Used to intercept requests and specify where to read the Spring MVC configuration file.

The < init ParM > is configured in the < servlet > tag to initialize the current servlet. It belongs to the configuration of the current servlet, so it is stored in the servletConfig object (servlet object).

It can be obtained by getServletConfig().getInitParameter("initParam").

[configure in web.xml]

<! -- Step2: configure the front-end controller of spring MVC to intercept all requests -- >
<servlet>
    <servlet-name>springmvcDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>
        <param-name>contextConfigLocation</param-name>
        <! -- if no value is provided, WEB-INF/*-servlet.xml will be found by defau lt. >
        <param-value>classpath:dispatcher-servlet.xml</param-value>
    </init-param>
    <! -- start priority, smaller value, higher priority -- >
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvcDispatcherServlet</servlet-name>
    <! -- if the dispatcher servlet request mapping is configured as "/", Spring MVC will capture all requests of the Web container, including those of static resources -- >
    <url-pattern>/</url-pattern>
</servlet-mapping>

Note:

When the spring framework loads the web configuration file. The content of the context param configuration is loaded first, without initializing the servlet. Only after the website jump and the dispatcher servlet, the servlet will be initialized to load the content in init param.

 

3. Configure the filter to solve the problem of disorderly code

Used to solve the problem of garbled code.

[configure in web.xml]

<! -- Step3: characterencodingfilter, put in front of all filters -- >
<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <! -- character set to be used, generally we use UTF-8 (UTF-8 is best for safety) - >
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <! -- whether to force the encoding of request to encoding, which is false by defau lt. It is not recommended to change -- >
        <param-name>forceRequestEncoding</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <! -- whether to force the response code to encoding, and it is recommended to set it to true -- >
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <! -- you cannot leave it blank or write '/' directly, otherwise it may not work -- >
    <url-pattern>/*</url-pattern>
</filter-mapping>

 

4. Configure the Rest style URI

Because browser form forms only support GET and POST requests, but DELETE, PUT and other methods are not supported. Spring 3.0 adds a filter (HiddenHttpMethodFilter), which can convert these requests into standard http methods, so that GET, POST, PUT and DELETE requests are supported.

[stay web.xml Configuration]

<!-- step4: Configure filters to post Request turned to delete,put -->
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Note:

The loading order of web.xml is: [context param - > listener - > filter - > servlet - > spring], while the actual program calling order between nodes of the same type is based on the corresponding mapping order.

 

5. Complete configuration of web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- step1: Configure global parameters, start Spring container -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- If no value is provided, the default is to find/WEB-INF/applicationContext.xml.  -->
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- step2: To configure SpringMVC To intercept all requests  -->
    <servlet>
        <servlet-name>springmvcDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- If no value is provided, the default is to find WEB-INF/*-servlet.xml.  -->
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
        <!-- Start priority, smaller value, higher priority -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvcDispatcherServlet</servlet-name>
        <!-- take DispatcherServlet Request mapping is configured as"/",be Spring MVC Will capture Web Container all requests, including requests for static resources -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- step3: characterEncodingFilter Character encoding filter, before all filters -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <!--To use the character set, we usually use UTF-8(Insurance UTF-8 Best)-->
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <!--Force setting or not request The encoding is encoding,default false,Change not recommended-->
            <param-name>forceRequestEncoding</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <!--Force setting or not response The encoding is encoding,Recommended setting is true-->
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!--It can't be left blank or written directly here ' / ' ,Otherwise, it may not work-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- step4: Configure filters to post Request turned to delete,put -->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

 

3. (3.2) configure spring MVC -- dispatcher-servlet.xml

1. Configure component scanning mode

Used to get related components. Generally, in Spring MVC configuration, only the Controller layer is scanned. In Spring configuration, all packages are scanned, but the Controller layer is excluded.

[configure in dispatcher-servlet.xml]

<! -- step1: configure Controller scanning mode -- >
<! -- you can scan mu lt iple controllers at a time by using component scanning, just specify the package path -- >
<context:component-scan base-package="com.lyh.ssm.crud" use-default-filters="false">
    <! -- in Spring MVC configuration, only the Controller layer is scanned. In Spring configuration, all packages are scanned, but the Controller layer is excluded.
    Context: include filter please note that if base package is not scanning the final package, other packages will still be scanned and loaded. If you do this in Spring MVC configuration, Spring will not be able to process transactions,
    So at this time, you need to add use default filters = "false" on the < context: component scan > tag, that is, only scan the content included in context: include filter -- >
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>



<! -- the way to configure a single Controller (which can be used in some special cases). You need to specify the fully qualified name of the Controller -- >
<!-- <bean name="/get" class="com.wxisme.ssm.controller.Controller1"/> -->

 

2. Configure view resolver

When you set the view name, prefixes and suffixes are automatically added.

[configure in dispatcher-servlet.xml]

<! -- Step2: configure the view resolver. When setting the view name, the prefix and suffix will be added automatically -- >
<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    < property name = "prefix" value = "/ WEB-INF /" / >
    <property name="suffix" value=".jsp"/>
</bean>

 

3. Configuration request processing (standard configuration I)

If the dispatcher servlet request mapping is configured as "/", then Spring MVC will capture all the requests of the Web container (including the requests of static resources), and Spring MVC will treat them as a normal request, so failure to find the corresponding processor will result in an error. So in order to enable the Spring framework to capture all URL requests, and at the same time transfer the static resource requests to the Web container for processing, under the premise that the request mapping of dispatcher servlet is configured as "/", the static requests can be handed over to the server for processing by using < MVC: default servlet handler / >.

[configure in dispatcher-servlet.xml]

<! -- an org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler will be defined in the context of Spring MVC. It will act as an inspector to screen the URL entering the DispatcherServlet. If it is found that the request is a static resource, the request will be transferred to the default Servlet of the Web application server for processing. If it is not a static resource, the request will be dispatched Rservlet continues processing. >
<mvc:default-servlet-handler />

 

4. Configure the annotated processor mapper and processor adapter (standard configuration 2)

< MVC: annotation driven / > simplifies annotation configuration and provides some advanced functions, such as support for JSR-303 validation of JavaBeans with @ Valid, support for @ RequestBody, @ ResponseBody.

[configure in dispatcher-servlet.xml]
[mode 1:]
<! -- configure annotated processor mapper and processor adapter (simplified configuration) - >
<mvc:annotation-driven />

[mode 2:]
<! -- annotated processor adapter -- >
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
<! -- annotated processor mapper -- >
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->

 

5. Complete configuration of dispatcher-servlet.xml

<?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:context="http://www.springframework.org/schema/context"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- step1: To configure Controller Scanning mode -->
    <!-- You can scan more than one at a time using component scanning Controller,Just specify the package path -->
    <context:component-scan base-package="com.lyh.ssm.crud" use-default-filters="false">
        <!-- Generally in SpringMVC In the configuration of, scan only Controller Layer, Spring Scan all packages in configuration, but exclude Controller Layer.
        context:include-filter Note that if base-package If the final package is not scanned, other packages will be scanned and loaded SpringMVC This will result in Spring Unable to process transaction,
        //So at this time, you need to add use default filters = "false" on the < context: component scan > tag, that is, only scan the content included in context: include filter-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- step2: Configure view resolver -->
    <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"/><!--Set up JSP Directory location of files-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- step3: Standard configuration -->
    <!-- take springmvc Unprocessable requests to spring Container handling -->
    <mvc:default-servlet-handler/>
    <!-- Simplify annotation configuration and provide more advanced functions -->
    <mvc:annotation-driven />
</beans>

 

3. (3.3) configure Spring--applicationContext.xml

1. Configure component scanning mode

It is used to obtain related components. Generally, all packages are scanned in the Spring configuration file, but the Controller layer is excluded.

[configure in applicationContext.xml]

<! -- step1: configure package scanning mode. Scan all packages, but exclude the Controller layer -- >
<context:component-scan base-package="com.lyh.ssm.crud">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

 

2. Configure database connection pool

For database operations.

[Method 1: directly fill in the connection parameters]
[stay applicationContext.xml Configuration]
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!--Injection attribute-->
    <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/lyh?useUnicode=true&characterEncoding=utf8"></property>
    <property name="user" value="root"></property>
    <property name="password" value="123456"></property>
</bean>

[Mode 2: through properties Get connection parameters by file]
[dbconfig.properties]
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/lyh?useUnicode=true&characterEncoding=utf8
jdbc.username = root
jdbc.password = 123456

[stay applicationContext.xml Configuration]
<!-- Introduce properties file -->
<context:property-placeholder location="classpath:dbconfig.properties" />

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!--Injection attribute-->
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

 

III. (3.4) Spring and MyBatis integrated configuration -- applicationContext.xml

The jar package is provided by MyBatis.

1. Configure sqlSessionFactory

[configure in applicationContext.xml]

<! -- Step3: integration of spring and mybatis -- >
<! -- to configure sqlSessionFactory, you need to introduce the mybatis spring package -- >
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <! -- load Mybatis global configuration file -- >
    <property name="configLocation" value="classpath:mybatis-config.xml"/>

    <! -- database connection pool -- >
    <property name="dataSource" ref="dataSource"/>

    <! -- configure mapper file location, scan map file -- >
    <property name="mapperLocations" value="classpath:mappers/*.xml"/>
</bean>

2. Configure the sqlsession to be executed in batch (optional operation)

[stay applicationContext.xml Configuration]

<!-- step4: Configure batch executed sqlSession(Optional operation) -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <constructor-arg name="executorType" value="BATCH"/>
</bean>

 

3. Configure mapper scanner

[configure in applicationContext.xml]

<! -- step5: configure the mapper scanner and add it to the ioc container -- >
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <! -- scan package path, if you need to scan mu lt iple packages, separate them with half angle comma -- >
    <property name="basePackage" value="com.lyh.ssm.crud.dao"></property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

 

4. Configure transaction control and aspect (optional)

[configure in applicationContext.xml]

<! -- step6: configure transaction control -- >
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <! -- configure data source -- >
    <property name="dataSource" ref="dataSource"/>
</bean>

<! -- configure transaction notification -- >
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <! -- Communication Behavior -- >
        <tx:method name="post*" propagation="REQUIRED"/>
        <tx:method name="put*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
</tx:advice>

<! -- configure AOP -- >
<aop:config>
    <! -- configure transaction enhancement, specify pointcut expression, the first * means to return any type, the second * means any method, (..) means any number and type of parameters -- >
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lyh.ssm.crud.service..*(..))"/>
</aop:config>

 

5. Complete configuration of applicationContext.xml

[db.properties]
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/lyh?useUnicode=true&characterEncoding=utf8
jdbc.username = root
jdbc.password = 123456



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

    <!-- step1: Configure package scanning mode. Scan all packages, but exclude Controller layer -->
    <context:component-scan base-package="com.lyh.ssm.crud">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- step2: Configure database connection information -->
    <!-- Introduce properties file -->
    <context:property-placeholder location="classpath:db.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--Injection attribute-->
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- step3: spring And mybatis integration -->
    <!-- To configure sqlSessionFactory,Need to introduce mybatis-spring package -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- Load Mybatis Global profile -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>

        <!-- Database connection pool -->
        <property name="dataSource" ref="dataSource"/>

        <!-- To configure mapper File location, scanning mapped files -->
        <property name="mapperLocations" value="classpath:mappers/*.xml"/>
    </bean>

    <!-- step4: Configure batch executed sqlSession(Optional operation) -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        <constructor-arg name="executorType" value="BATCH"/>
    </bean>

    <!-- step5: To configure mapper Scanner, adding it to ioc Container -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- Scan package path, if you need to scan multiple packages, separate them with half angle comma -->
        <property name="basePackage" value="com.lyh.ssm.crud.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!-- step6: Configure transaction control -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- Configure data sources -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- Configure transaction notifications -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- Communication behavior -->
            <tx:method name="post*" propagation="REQUIRED"/>
            <tx:method name="put*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- To configure aop -->
    <aop:config>
        <!-- Configure transaction enhancement, specify pointcut expression, first*Indicates to return any type, the second*Represents any method(..)Parameters representing any number and type-->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lyh.ssm.crud.service..*(..))"/>
    </aop:config>
</beans>

 

III. (3.5) Mybatis configuration -- mybatis-config.xml

1. Configure global parameters

[configure in mybatis-config.xml]

<settings>
    <! -- enable hump naming rules -- >
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

 

2. Use page helper

[stay mybatis-config.xml Configuration]

<plugins>
   <!-- Using the paging plug-in -->
   <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

 

3. Complete configuration of mybatis-config.xml

[mybatis-config.xml]
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- Turn on hump naming rules -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <plugins>
        <!-- Using the paging plug-in -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
</configuration>

 

IV. reverse engineering

Reference: https://www.cnblogs.com/l-y-h/p/11748300.html

1. Configuration file: src/mybatis-generator.xml

[src/mybatis-generator.xml]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!-- Clear comment information -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!-- step1: Configure database connection information -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/lyh"
                        userId="root"
                        password="123456">
        </jdbcConnection>

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- step2: Appoint java bean Generated location
            targetProject Which project is it
            targetPackage Refers to the path in the project
        -->
        <javaModelGenerator targetPackage="com.lyh.ssm.crud.bean" targetProject=".\src">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- step3: Appoint sql Location of map file generation -->
        <sqlMapGenerator targetPackage="com.lyh.ssm.crud.mapper" targetProject=".\src">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!-- step4: Specify the location of the interface build -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.lyh.ssm.crud.dao" targetProject=".\src">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!-- step5: Specify the generation policy for the table
            tableName Specified table name
            domainObjectName Specifies the name of the entity class corresponding to the table
        -->
        <table tableName="emp" domainObjectName="Employee"></table>
        <table tableName="dept" domainObjectName="Department"></table>
    </context>
</generatorConfiguration>

 

2. Execution class -- TestMybatisGenerator

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class TestMybatisGenerator {
    public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("src//mybatis-generator.xml");
        System.out.println(configFile);
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

 

Note:

After the file is generated, the location may not be correct. You need to manually copy the file to the appropriate location.

 

 

V. database (mysql 1.8)

1. Create data table

emp
    -- Create a emp Table, in which id Is the primary key and is self increasing.
    CREATE TABLE emp(
        id int primary key auto_increment,
        name varchar(50),
        salary double,
        age int,
        email varchar(50)
    );

dept
    -- Create a dept Table, in which deptId Is auto increment primary key
    CREATE TABLE dept(
        deptId INT(11) PRIMARY KEY AUTO_INCREMENT,
        deptName VARCHAR(255)
    );
    
    -- to emp Add a column to the table
    ALTER TABLE emp ADD COLUMN deptId INT(11);
    
    -- And will emp The column in is associated with the dept Primary key
    ALTER TABLE emp ADD CONSTRAINT fk_emp_dept FOREIGN KEY(deptId) REFERENCES dept(deptId);

 

2. Insert some data (optional operation)

dept
    INSERT INTO dept(deptId, deptName) VALUES(1, 'Development Department');
    INSERT INTO dept(deptId, deptName) VALUES(2, 'Test department');
    INSERT INTO dept(deptId, deptName) VALUES(3, 'Product department');

emp(id Self increasing, insert a null that will do)
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'tom', '8000', 23, 'tom@163.com', 1);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'jarry', '7000', 23, 'jarry@163.com', 2);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'rick', '9000', 23, 'rick@163.com', 3);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'rose', '11000', 23, 'rose@163.com', 3);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'tim', '3300', 23, 'tim@163.com', 2);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'silla', '9100', 23, 'silla@163.com', 1);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'jack', '10000', 23, 'jack@163.com', 1);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'lisa', '6000', 23, 'lisa@163.com', 2);
    INSERT INTO emp(id, name, salary, age, email, deptId) VALUES(null, 'mina', '9000', 23, 'mina@163.com', 2);

 

3. Test the interaction between background code and database (optional operation)

[stay applicationContext.xml Configure batch execution of sqlSession]
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <constructor-arg name="executorType" value="BATCH"/>
</bean>


[Test class TestCodeEnvironment.java]

import com.lyh.ssm.crud.bean.Department;
import com.lyh.ssm.crud.bean.Employee;
import com.lyh.ssm.crud.dao.DepartmentMapper;
import com.lyh.ssm.crud.dao.EmployeeMapper;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.UUID;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestCodeEnvironment {
    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    DepartmentMapper departmentMapper;

    @Autowired
    SqlSession sqlSession;

    @Test
    public void testDept() {
        departmentMapper.insertSelective(new Department(null, "Development Department"));
        departmentMapper.insertSelective(new Department(null, "Test department"));
    }

    @Test
    public void testEmp() {
        // Batch execution sql Sentence
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        for (int i = 0; i < 2; i++){
            String name = UUID.randomUUID().toString().substring(0, 5) + i;
            employeeMapper.insertSelective(new Employee(null, name, 1000.0, 20, "jarry@163.com",1));
        }
    }
}

 

 

 

Vi. back end code

1. Document structure

 

 

 

 

2, code

[com.lyh.ssm.crud.model.BaseModel]

package com.lyh.ssm.crud.model; import java.util.ArrayList; import java.util.List; /** * Base return type, * messages Used to save returned information * level Level used to save information * Level Is an enumeration type */ public class BaseModel { private List<String> messages = new ArrayList<String>(); private Level level = Level.info; private Boolean success = true; public Boolean getSuccess() { return success; } public void setSuccess(Boolean success) { this.success = success; } public List<String> getMessages() { return messages; } public void setMessages(List<String> messages) { this.messages = messages; } public Level getLevel() { return level; } public void setLevel(Level level) { this.level = level; } public enum Level { info, warn, error } public void addMessage(String message) { this.messages.add(message); } }

[com.lyh.ssm.crud.model.DeptModel]

package com.lyh.ssm.crud.model; import com.lyh.ssm.crud.bean.Department; import java.util.List; public class DeptModel extends BaseModel { private List<Department> departments; public List<Department> getDepartments() { return departments; } public void setDepartments(List<Department> departments) { this.departments = departments; } }

[com.lyh.ssm.crud.model.EmpModel]


package com.lyh.ssm.crud.model; import com.lyh.ssm.crud.bean.Employee; import java.util.ArrayList; import java.util.List; /** * Employee return information class, used to return employee information */ public class EmpModel extends BaseModel { private List<Employee> employeeList = new ArrayList<Employee>(); public List<Employee> getEmployeeList() { return employeeList; } public void setEmployeeList(List<Employee> employeeList) { this.employeeList = employeeList; } public void addEmployee(Employee emp) { this.employeeList.add(emp); } }
[com.lyh.ssm.crud.model.EmpPageModel]
package com.lyh.ssm.crud.model; import com.github.pagehelper.PageInfo; public class EmpPageModel extends BaseModel { private PageInfo pageInfo; public PageInfo getPageInfo() { return pageInfo; } public void setPageInfo(PageInfo pageInfo) { this.pageInfo = pageInfo; } }

[com.lyh.ssm.crud.controller.EmpController] package com.lyh.ssm.crud.controller; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.lyh.ssm.crud.bean.Employee; import com.lyh.ssm.crud.model.BaseModel; import com.lyh.ssm.crud.model.EmpModel; import com.lyh.ssm.crud.model.EmpPageModel; import com.lyh.ssm.crud.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.
*; import java.util.List; @RestController public class EmpController { @Autowired private EmpService empService; /** * Get paged data * @param pageNum Get data on page * @param pageSize Number of returned data * @return Return data */ @GetMapping("/emps/{pageNum}") public EmpPageModel getAllEmp(@PathVariable Integer pageNum, @RequestParam Integer pageSize) { // step1:Introducing paging plug-ins(PageHelper) // step2:Before each query, set the query page and the number of queries, and obtain 5 pieces of data each time PageHelper.startPage(pageNum, pageSize); // step3:Execute paging query List<Employee> employeeList = empService.getAllEmp(); // step4:Data after package query PageInfo pageInfo = new PageInfo(employeeList); EmpPageModel empPageModel = new EmpPageModel(); if (employeeList.size() <= 0) { empPageModel.addMessage("Failed to get paging data"); empPageModel.setSuccess(false); empPageModel.setLevel(BaseModel.Level.error); return empPageModel; } empPageModel.addMessage("Paging data obtained successfully"); empPageModel.setSuccess(true); empPageModel.setLevel(BaseModel.Level.info); empPageModel.setPageInfo(pageInfo); return empPageModel; } /** * Get information about an employee * REST -- GET * @param id Employee id * @return Return data */ @GetMapping("/emp/{id}") public EmpModel getEmpById(@PathVariable Integer id) { EmpModel empModel = new EmpModel(); if (empService.getEmpById(id) == null) { empModel.addMessage("Failed to get employee information"); empModel.setSuccess(false); empModel.setLevel(BaseModel.Level.error); return empModel; } empModel.addMessage("Get employee information successfully"); empModel.setSuccess(true); empModel.setLevel(BaseModel.Level.info); empModel.addEmployee(empService.getEmpById(id)); return empModel; } /** * Delete an employee's information * REST -- DELETE * @param id Employee id * @return Return data */ @RequestMapping(value = "/emp/{id}", method = RequestMethod.DELETE) public BaseModel deleteEmpById(@PathVariable Integer id) { BaseModel baseModel = new BaseModel(); if (empService.deleteEmpById(id) != 0) { baseModel.addMessage("Delete employee information succeeded"); baseModel.setSuccess(true); baseModel.setLevel(BaseModel.Level.info); return baseModel; } baseModel.addMessage("Failed to delete employee information"); baseModel.setSuccess(false); baseModel.setLevel(BaseModel.Level.error); return baseModel; } /** * Insert employee information into employee table * REST -- POST * When using @ RequestBody, please note that the parameter name passed in the foreground corresponds to the parameter name in the Employee, otherwise no value will be received * @param employee Employee information * @return Return data */ @PostMapping("/emp") public BaseModel insertEmp(@RequestBody Employee employee) { BaseModel baseModel = new BaseModel(); if (empService.insertEmp(employee) != 0) { baseModel.addMessage("Insert employee information succeeded"); baseModel.setSuccess(true); baseModel.setLevel(BaseModel.Level.info); return baseModel; } baseModel.addMessage("Failed to insert employee information"); baseModel.setSuccess(false); baseModel.setLevel(BaseModel.Level.error); return baseModel; } /** * Update employee information * REST -- PUT * @param employee Employee information * @return Return data */ @RequestMapping(value = "/emp/{id}", method = RequestMethod.PUT) public BaseModel updateEmp(@RequestBody Employee employee) { BaseModel baseModel = new BaseModel(); if (empService.updateEmp(employee) != 0) { baseModel.addMessage("Update employee information succeeded"); baseModel.setSuccess(true); baseModel.setLevel(BaseModel.Level.info); return baseModel; } baseModel.addMessage("Failed to update employee information"); baseModel.setSuccess(false); baseModel.setLevel(BaseModel.Level.error); return baseModel; } } [com.lyh.ssm.crud.controller.DeptController] package com.lyh.ssm.crud.controller; import com.lyh.ssm.crud.model.BaseModel; import com.lyh.ssm.crud.model.DeptModel; import com.lyh.ssm.crud.service.DeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DeptController { @Autowired private DeptService deptService; @GetMapping("/depts") public DeptModel getAllDept() { DeptModel deptModel = new DeptModel(); if (deptService.getAllDept().size() <= 0) { deptModel.addMessage("Failed to get department information"); deptModel.setSuccess(false); deptModel.setLevel(BaseModel.Level.error); return deptModel; } deptModel.addMessage("Obtain department information successfully"); deptModel.setSuccess(true); deptModel.setLevel(BaseModel.Level.info); deptModel.setDepartments(deptService.getAllDept()); return deptModel; } } [com.lyh.ssm.crud.service.DeptService] package com.lyh.ssm.crud.service; import com.lyh.ssm.crud.bean.Department; import com.lyh.ssm.crud.dao.DepartmentMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class DeptService { @Autowired private DepartmentMapper departmentMapper; public List<Department> getAllDept() { return departmentMapper.selectAll(); } } [com.lyh.ssm.crud.service.EmpService] package com.lyh.ssm.crud.service; import com.lyh.ssm.crud.bean.Employee; import com.lyh.ssm.crud.dao.EmployeeMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class EmpService { @Autowired private EmployeeMapper employeeMapper; /** * Get information about an employee * * @param id id of an employee * @return Information about an employee */ public Employee getEmpById(Integer id) { return employeeMapper.selectByPrimaryKey(id); } /** * Get information about all employees * * @return Information for all employees */ public List<Employee> getAllEmp() { return employeeMapper.selectAll(); } /** * Insert information about an employee * * @param emp Information about an employee * @return Returns the number of rows affected by the insertion */ public Integer insertEmp(Employee emp) { return employeeMapper.insertSelective(emp); } /** * Delete an employee's information * * @param id Employee id * @return Return the number of rows affected by deletion */ public Integer deleteEmpById(Integer id) { return employeeMapper.deleteByPrimaryKey(id); } /** * Update an employee's information * @param employee Employee information * @return Returns the number of rows affected by the modification */ public Integer updateEmp(Employee employee) { return employeeMapper.updateByPrimaryKeySelective(employee); } }

[com.lyh.ssm.crud.dao.DepartmentMapper]
package com.lyh.ssm.crud.dao; import com.lyh.ssm.crud.bean.Department; import com.lyh.ssm.crud.bean.DepartmentExample; import java.util.List; import org.apache.ibatis.annotations.Param; public interface DepartmentMapper { long countByExample(DepartmentExample example); int deleteByExample(DepartmentExample example); int deleteByPrimaryKey(Integer deptid); int insert(Department record); int insertSelective(Department record); List<Department> selectByExample(DepartmentExample example); Department selectByPrimaryKey(Integer deptid); int updateByExampleSelective(@Param("record") Department record, @Param("example") DepartmentExample example); int updateByExample(@Param("record") Department record, @Param("example") DepartmentExample example); int updateByPrimaryKeySelective(Department record); int updateByPrimaryKey(Department record); List<Department> selectAll(); }

[com.lyh.ssm.crud.dao.EmployeeMapper]
package com.lyh.ssm.crud.dao; import com.lyh.ssm.crud.bean.Employee; import com.lyh.ssm.crud.bean.EmployeeExample; import java.util.List; import org.apache.ibatis.annotations.Param; public interface EmployeeMapper { long countByExample(EmployeeExample example); int deleteByExample(EmployeeExample example); int deleteByPrimaryKey(Integer id); int insert(Employee record); int insertSelective(Employee record); List<Employee> selectByExample(EmployeeExample example); List<Employee> selectAll(); Employee selectByPrimaryKey(Integer id); int updateByExampleSelective(@Param("record") Employee record, @Param("example") EmployeeExample example); int updateByExample(@Param("record") Employee record, @Param("example") EmployeeExample example); int updateByPrimaryKeySelective(Employee record); int updateByPrimaryKey(Employee record); } [mappers
/DepartmentMapper.xml Add method] <select id="selectAll" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from dept </select> [mappers/EmployeeMapper.xml] <select id="selectAll" resultMap="BaseResultMap"> SELECT e.id AS id, e.name AS name, e.salary AS salary, e.age AS age, e.email AS email, d.deptId AS deptId, d.deptName AS deptName FROM emp e LEFT JOIN dept d ON e.deptId = d.deptId ORDER BY e.id </select> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> SELECT e.id AS id, e.name AS name, e.salary AS salary, e.age AS age, e.email AS email, d.deptId AS deptId, d.deptName AS deptName FROM emp e LEFT JOIN dept d ON e.deptId = d.deptId WHERE e.id = #{id,jdbcType=INTEGER} </select>

 

7. Front end code - static page

1. In non template/render mode

In this case, some component names need to be prefixed with i - before they can be used.

For example:

  Button  -->  i-button

  Table    -->  i-table

  Select  -->  i-select

  Option  -->  i-option

  Form    -->  i-form

  FormItem  -->  form-item

[wrong template/render Mode]

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ViewUI example</title>
    <link rel="stylesheet" type="text/css" href="http://unpkg.com/view-design/dist/styles/iview.css">
    <script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>
    <script type="text/javascript" src="http://unpkg.com/view-design/dist/iview.min.js"></script>
</head>
<body>
<div id="app">
    <div style="width: 1200px; margin: 0 auto;" class="layout">
        <Layout>
            <header>
                <row>
                    <Divider orientation="left">
                        <h1>Employee list</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><i-button type="primary" icon="md-add" @click="create">Add to</i-button></i-col>
                    <i-col style="margin-right: 5px"><i-button type="success" icon="md-settings" @click="setUp = true">Set up</i-button></i-col>
                </row>
            </header>
            <Content>
                <i-table :data="data2" :columns="tableColumns1" :stripe="showStripe" :border="showBorder" :showHeader="showHeader" :size="tableSize" :height="fixedHeader ? 250 : ''">
                    <template slot-scope="{ row }" slot="name">
                        <strong>{{ row.name }}</strong>
                    </template>
                    <template slot-scope="{ row, index }" slot="action">
                        <i-button type="primary" size="small" style="margin-right: 5px" @click="show(index)" icon="ios-create-outline">edit</i-button>
                        <i-button type="error" size="small" @click="remove(index)" icon="ios-trash">delete</i-button>
                    </template>
                </i-table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current Set the currently selected page,pageSize Set the number of displayed data per page-->
                        <Page :total="data1.length" :pageSize="pageSize" :current="currentPage" @on-change="changePage" show-sizer show-elevator show-total @on-page-size-change="changePageSize"></Page>
                    </div>
                </div>
            </Content>
        </Layout>
    
        <Drawer title="Set up" :closable="true" :mask="false" v-model="setUp">
            <div style="margin: 10px">
                Table Setting<br>
                <i-switch v-model="showBorder" style="margin-right: 5px"></i-switch>Display border<br>
                <i-switch v-model="showStripe" style="margin-right: 5px"></i-switch>Display stripe<br>
                <i-switch v-model="showIndex" style="margin-right: 5px"></i-switch>Display index<br>
                <i-switch v-model="showCheckbox" style="margin-right: 5px"></i-switch>Display multi choice<br>
                <i-switch v-model="showHeader" style="margin-right: 5px"></i-switch>Display header<br>
                <i-switch v-model="fixedHeader" style="margin-right: 5px"></i-switch>Table scrolling<br>
                <br><br>
        
                Table size
                <i-select v-model="tableSize" style="width:200px">
                    <i-option value="large">large</i-option>
                    <i-option value="default">medium(default)</i-option>
                    <i-option value="small">small</i-option>
                </i-select>
            </div>
        </Drawer>
    
        <Modal v-model="empModal" title="Emp Info" @on-ok="okEditor" @on-cancel="cancelEditor">
            <i-form :label-width="80">
                <form-item label="Name:">
                    <i-input v-model="empInfo.name" placeholder="Name..." style="width: 300px;" />
                </form-item>
                <form-item label="Salary:">
                    <i-input v-model="empInfo.salary" placeholder="Salary..." style="width: 300px;" />
                </form-item>
                <form-item label="Age:">
                    <i-input v-model="empInfo.age" placeholder="Age..." style="width: 300px;" />
                </form-item>
                <form-item label="Email:">
                    <i-input v-model="empInfo.email" placeholder="Email..." style="width: 300px;" />
                </form-item>
                <form-item label="DeptName:">
                    <i-select v-model="empInfo.deptName">
                        <i-option v-for="(item, index) in dept" :key="index" :value="item.deptName"> {{item.deptName}} </i-option>
                    </i-select>
                </form-item>
            </i-form>
        </Modal>
    </div>
</div>
<script>
    new Vue({
        el: '#app',
        data() {
            return {
                // Add and edit reuse modal Box, false To add, true Editors
                createOrEditor: false,
                // Open employee information box
                empModal: false,
                // Information used to save an employee
                empInfo: {},
                // Open settings or not
                setUp: false,
                // Current page number
                currentPage: 1,
                // Number of data per page
                pageSize: 10,
                // Column of tables
                tableColumns1: [{
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    }, {
                        title: 'Name',
                        slot: 'name'
                    }, {
                        title: 'Salary',
                        key: 'salary',
                        sortable: true
                    },
                    {
                        title: 'Age',
                        key: 'age',
                        sortable: true
                    },
                    {
                        title: 'Email',
                        key: 'email'
                    }, {
                        title: 'DeptName',
                        key: 'deptName'
                    },
                    {
                        title: 'Action',
                        slot: 'action',
                        width: 200,
                        align: 'center'
                    }
                ],
                dept: [{
                    deptId: '1',
                    deptName: 'Development Department'
                },{
                    deptId: '2',
                    deptName: 'Test department'
                },{
                    deptId: '3',
                    deptName: 'Product department'
                }],
                // Table's source data
                data1: [{
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: 'Product department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    }, {
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: 'Product department'
                    }
                ],
                // Data per page of table
                data2: [],
                // Whether the table border is displayed
                showBorder: false,
                // Table whether zebra stripes are displayed
                showStripe: false,
                // Whether the table header is displayed
                showHeader: true,
                // Whether the table index is displayed
                showIndex: true,
                // Whether the table multi selection box is displayed
                showCheckbox: false,
                // Whether the table scroll bar is on
                fixedHeader: false,
                // Change table size
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // Change the current page number and obtain the data owned by the current page number
                this.currentPage = index
                // Note that it cannot be used directly here = Assignment. Use = After (pointing to the same address), modify data2 It will be modified at the same time data1
                this.data2 = [].concat(this.data1.slice((index - 1) * this.pageSize, index * this.pageSize))
            },
            show(index) {
                // Pop up a modal box to show the information of a piece of data
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {index: index})
            },
            create() {
                // Used to add a message
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(index) {
                // Delete a piece of data (delete source data)
                this.data1.splice((this.currentPage - 1) * 10 + index, 1)
            },
            changePageSize(index) {
                // Change the number of items displayed per page
                this.$Message.info({
                    content: 'The number of items displayed on the current page is modified to: ' + index + 'strip/page'
                })
                // After the change, jump to the home page and refresh the list
                this.currentPage = 1
                this.pageSize = index
                this.changePage(this.currentPage)
            },
            okEditor () {
                if (this.createOrEditor) {
                    // Edit action,Modifying data
                    this.data1.splice((this.currentPage - 1) * 10 + this.empInfo.index, 1, this.empInfo)
                } else {
                    // Add operation, modify data
                    this.data1.push(Object.assign({}, this.empInfo))
                }
                this.empInfo = {}
            },
            cancelEditor () {
                // Cancel editing
                this.$Message.info({
                    content: 'Operation cancelled'
                })
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // by true Add an index column to the first
                    this.tableColumns1.unshift({
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // by false If there is an index column in the first part, the column will be removed
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // by true Add a multi check box column in the first part,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // by false If there is more than one box column, remove it
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            data1() {
                // When the list data changes (such as deleting some data), a refresh of the list will be triggered
                if (!this.createOrEditor) {
                    // To add data, go to the last page
                    this.changePage(Math.ceil(this.data1.length / this.pageSize))
                } else {
                    this.changePage(this.currentPage)
                }
            }
        },
        mounted() {
            // When the page is loaded, the first refresh of the list is triggered
            this.changePage(this.currentPage)
        }
    })
</script>
</body>
</html>

 

 

 

 

 

 

2. In template/render mode

(1) use vue-cli 3.0 to create the project.

Reference address: https://www.cnblogs.com/l-y-h/p/11241503.html

 

(2) npm is used for installation.

Reference address: https://www.cnblogs.com/l-y-h/p/1200549.html × label0 × 1

[main.js]

import Vue from 'vue'
import App from './App.vue'
// step1: introducing ViewUI
import ViewUI from 'view-design'
// Step 2: introduce css 
import 'view-design/dist/styles/iview.css'

Vue.config.productionTip = false
// step3: declare using ViewUI
Vue.use(ViewUI)

new Vue({
  render: h => h(App),
}).$mount('#app')



[App.vue]
<template>
    <div style="width: 1200px; margin: 0 auto;" class="layout">
        <Layout>
            <header>
                <row>
                    <Divider orientation="left">
                        <h1>Employee list</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><Button type="primary" icon="md-add" @click="create">Add to</Button></i-col>
                    <i-col style="margin-right: 5px"><Button type="success" icon="md-settings" @click="setUp = true">Set up</Button></i-col>
                </row>
            </header>
            <Content>
                <Table :data="data2" :columns="tableColumns1" :stripe="showStripe" :border="showBorder" :showHeader="showHeader" :size="tableSize" :height="fixedHeader ? 250 : ''">
                    <template slot-scope="{ row }" slot="name">
                        <strong>{{ row.name }}</strong>
                    </template>
                    <template slot-scope="{ row, index }" slot="action">
                        <Button type="primary" size="small" style="margin-right: 5px" @click="show(index)" icon="ios-create-outline">edit</Button>
                        <Button type="error" size="small" @click="remove(index)" icon="ios-trash">delete</Button>
                    </template>
                </Table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current Set the currently selected page,pageSize Set the number of displayed data per page-->
                        <Page :total="data1.length" :pageSize="pageSize" :current="currentPage" @on-change="changePage" show-sizer show-elevator show-total @on-page-size-change="changePageSize"></Page>
                    </div>
                </div>
            </Content>
        </Layout>

        <Drawer title="Set up" :closable="true" :mask="false" v-model="setUp">
            <div style="margin: 10px">
                Table Setting<br>
                <i-switch v-model="showBorder" style="margin-right: 5px"></i-switch>Display border<br>
                <i-switch v-model="showStripe" style="margin-right: 5px"></i-switch>Display stripe<br>
                <i-switch v-model="showIndex" style="margin-right: 5px"></i-switch>Display index<br>
                <i-switch v-model="showCheckbox" style="margin-right: 5px"></i-switch>Display multi choice<br>
                <i-switch v-model="showHeader" style="margin-right: 5px"></i-switch>Display header<br>
                <i-switch v-model="fixedHeader" style="margin-right: 5px"></i-switch>Table scrolling<br>
                <br><br>
        
                Table size
                <Select v-model="tableSize" style="width:200px">
                    <Option value="large">large</Option>
                    <Option value="default">medium(default)</Option>
                    <Option value="small">small</Option>
                </Select>
            </div>
        </Drawer>

        <Modal v-model="empModal" title="Emp Info" @on-ok="okEditor" @on-cancel="cancelEditor">
            <Form :label-width="80">
                <FormItem label="Name:">
                    <Input v-model="empInfo.name" placeholder="Name..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Salary:">
                    <Input v-model="empInfo.salary" placeholder="Salary..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Age:">
                    <Input v-model="empInfo.age" placeholder="Age..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Email:">
                    <Input v-model="empInfo.email" placeholder="Email..." style="width: 300px;" />
                </FormItem>
                <FormItem label="DeptName:">
                    <Select v-model="empInfo.deptName">
                        <Option v-for="(item, index) in dept" :key="index" :value="item.deptName"> {{item.deptName}} </Option>
                    </Select>
                </FormItem>
            </Form>
        </Modal>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                // Add and edit reuse modal Box, false To add, true Editors
                createOrEditor: false,
                // Open employee information box
                empModal: false,
                // Information used to save an employee
                empInfo: {},
                // Open settings or not
                setUp: false,
                // Current page number
                currentPage: 1,
                // Number of data per page
                pageSize: 10,
                // Column of tables
                tableColumns1: [{
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    }, {
                        title: 'Name',
                        slot: 'name'
                    }, {
                        title: 'Salary',
                        key: 'salary',
                        sortable: true
                    },
                    {
                        title: 'Age',
                        key: 'age',
                        sortable: true
                    },
                    {
                        title: 'Email',
                        key: 'email'
                    }, {
                        title: 'DeptName',
                        key: 'deptName'
                    },
                    {
                        title: 'Action',
                        slot: 'action',
                        width: 200,
                        align: 'center'
                    }
                ],
                dept: [{
                    deptId: '1',
                    deptName: 'Development Department'
                },{
                    deptId: '2',
                    deptName: 'Test department'
                },{
                    deptId: '3',
                    deptName: 'Product department'
                }],
                // Table's source data
                data1: [{
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: 'Product department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    }, {
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: 'Product department'
                    }
                ],
                // Data per page of table
                data2: [],
                // Whether the table border is displayed
                showBorder: false,
                // Table whether zebra stripes are displayed
                showStripe: false,
                // Whether the table header is displayed
                showHeader: true,
                // Whether the table index is displayed
                showIndex: true,
                // Whether the table multi selection box is displayed
                showCheckbox: false,
                // Whether the table scroll bar is on
                fixedHeader: false,
                // Change table size
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // Change the current page number and obtain the data owned by the current page number
                this.currentPage = index
                // Note that it cannot be used directly here = Assignment. Use = After (pointing to the same address), modify data2 It will be modified at the same time data1
                this.data2 = [].concat(this.data1.slice((index - 1) * this.pageSize, index * this.pageSize))
            },
            show(index) {
                // Pop up a modal box to show the information of a piece of data
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {index: index})
            },
            create() {
                // Used to add a message
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(index) {
                // Delete a piece of data (delete source data)
                this.data1.splice((this.currentPage - 1) * 10 + index, 1)
            },
            changePageSize(index) {
                // Change the number of items displayed per page
                this.$Message.info({
                    content: 'The number of items displayed on the current page is modified to: ' + index + 'strip/page'
                })
                // After the change, jump to the home page and refresh the list
                this.currentPage = 1
                this.pageSize = index
                this.changePage(this.currentPage)
            },
            okEditor () {
                if (this.createOrEditor) {
                    // Edit action,Modifying data
                    this.data1.splice((this.currentPage - 1) * 10 + this.empInfo.index, 1, this.empInfo)
                } else {
                    // Add operation, modify data
                    this.data1.push(Object.assign({}, this.empInfo))
                }
                this.empInfo = {}
            },
            cancelEditor () {
                // Cancel editing
                this.$Message.info({
                    content: 'Operation cancelled'
                })
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // by true Add an index column to the first
                    this.tableColumns1.unshift({
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // by false If there is an index column in the first part, the column will be removed
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // by true Add a multi check box column in the first part,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // by false If there is more than one box column, remove it
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            data1() {
                // When the list data changes (such as deleting some data), a refresh of the list will be triggered
                if (!this.createOrEditor) {
                    // To add data, go to the last page
                    this.changePage(Math.ceil(this.data1.length / this.pageSize))
                } else {
                    this.changePage(this.currentPage)
                }
            }
        },
        mounted() {
            // When the page is loaded, the first refresh of the list is triggered
            this.changePage(this.currentPage)
        }
    }
</script>

 

 

 

 

 

 

 

File directory structure:

 

 

 

 

 

VIII. Front end code

1. Solve cross domain problems

Please refer to: https://www.cnblogs.com/l-y-h/p/11815452.html

(1) configure baseURL in main.js

[main.js]

import Vue from 'vue'
import App from './App.vue'
import ViewUI from 'view-design'
import 'view-design/dist/styles/iview.css'
import Axios from 'axios'

Vue.config.productionTip = false
Vue.use(ViewUI)
Vue.prototype.$axios = Axios
Axios.defaults.baseURL = '/api'

new Vue({
  render: h => h(App),
}).$mount('#app')

 

(2) configure cross domain agent in vue.config.js

[vue.config.js]

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                // This is written to replace / api with http://localhost:9000/crud
                target: 'http://localhost:9000/crud/',
                // Cross domain allowed
                changeOrigin: true,
                ws: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
}

 

(3) using axios

 

 

 

[Customize a api.js Document]

import Axios from 'axios'

export function getAllEmps(params) {
    return new Promise((resolve, reject) => {
        Axios.get('/emps/' + params.pageNum, {
            params
        }).then(res => {
            resolve(res);
        }).catch(res => {
            reject(res)
        })
    })
}


[When using, introduce the js Documents only]
<template>
</template>
<script>
    import { getAllEmps } from './api/api.js'
    export default {
        data() {
            return {
                currentPage: 1,
                pageSize: 2
            }
        },
        mounted() {
            // No need to use this.getAllEmps(),Direct use getAllEmps() that will do
            getAllEmps({
                pageNum: this.currentPage,
                pageSize: this.pageSize
            })
        }
    }
</script>



[App.vue]

<template>
    <div style="width: 1200px; margin: 0 auto;" class="layout">
        <Layout>
            <header>
                <row>
                    <Divider orientation="left">
                        <h1>Employee list</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><Button type="primary" icon="md-add" @click="create">Add to</Button></i-col>
                    <i-col style="margin-right: 5px"><Button type="success" icon="md-settings" @click="setUp = true">Set up</Button></i-col>
                </row>
            </header>
            <Content>
                <Table :data="data2" :columns="tableColumns1" :stripe="showStripe" :border="showBorder" :showHeader="showHeader" :size="tableSize" :height="fixedHeader ? 250 : ''">
                    <template slot-scope="{ row }" slot="name">
                        <strong>{{ row.name }}</strong>
                    </template>
                    <template slot-scope="{ row, index }" slot="action">
                        <Button type="primary" size="small" style="margin-right: 5px" @click="show(index)" icon="ios-create-outline">edit</Button>
                        <Button type="error" size="small" @click="remove(index)" icon="ios-trash">delete</Button>
                    </template>
                </Table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current Set the currently selected page,pageSize Set the number of displayed data per page-->
                        <Page :total="data1.length" :pageSize="pageSize" :current="currentPage" @on-change="changePage" show-sizer show-elevator show-total @on-page-size-change="changePageSize"></Page>
                    </div>
                </div>
            </Content>
        </Layout>

        <Drawer title="Set up" :closable="true" :mask="false" v-model="setUp">
            <div style="margin: 10px">
                Table Setting<br>
                <i-switch v-model="showBorder" style="margin-right: 5px"></i-switch>Display border<br>
                <i-switch v-model="showStripe" style="margin-right: 5px"></i-switch>Display stripe<br>
                <i-switch v-model="showIndex" style="margin-right: 5px"></i-switch>Display index<br>
                <i-switch v-model="showCheckbox" style="margin-right: 5px"></i-switch>Display multi choice<br>
                <i-switch v-model="showHeader" style="margin-right: 5px"></i-switch>Display header<br>
                <i-switch v-model="fixedHeader" style="margin-right: 5px"></i-switch>Table scrolling<br>
                <br><br>
        
                Table size
                <Select v-model="tableSize" style="width:200px">
                    <Option value="large">large</Option>
                    <Option value="default">medium(default)</Option>
                    <Option value="small">small</Option>
                </Select>
            </div>
        </Drawer>

        <Modal v-model="empModal" title="Emp Info" @on-ok="okEditor" @on-cancel="cancelEditor">
            <Form :label-width="80">
                <FormItem label="Name:">
                    <Input v-model="empInfo.name" placeholder="Name..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Salary:">
                    <Input v-model="empInfo.salary" placeholder="Salary..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Age:">
                    <Input v-model="empInfo.age" placeholder="Age..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Email:">
                    <Input v-model="empInfo.email" placeholder="Email..." style="width: 300px;" />
                </FormItem>
                <FormItem label="DeptName:">
                    <Select v-model="empInfo.deptName">
                        <Option v-for="(item, index) in dept" :key="index" :value="item.deptName"> {{item.deptName}} </Option>
                    </Select>
                </FormItem>
            </Form>
        </Modal>
    </div>
</template>
<script>
    import { getAllEmps } from './api/api.js'
    export default {
        data() {
            return {
                // Add and edit reuse modal Box, false To add, true Editors
                createOrEditor: false,
                // Open employee information box
                empModal: false,
                // Information used to save an employee
                empInfo: {},
                // Open settings or not
                setUp: false,
                // Current page number
                currentPage: 1,
                // Number of data per page
                pageSize: 10,
                // Column of tables
                tableColumns1: [{
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    }, {
                        title: 'Name',
                        slot: 'name'
                    }, {
                        title: 'Salary',
                        key: 'salary',
                        sortable: true
                    },
                    {
                        title: 'Age',
                        key: 'age',
                        sortable: true
                    },
                    {
                        title: 'Email',
                        key: 'email'
                    }, {
                        title: 'DeptName',
                        key: 'deptName'
                    },
                    {
                        title: 'Action',
                        slot: 'action',
                        width: 200,
                        align: 'center'
                    }
                ],
                dept: [{
                    deptId: '1',
                    deptName: 'Development Department'
                },{
                    deptId: '2',
                    deptName: 'Test department'
                },{
                    deptId: '3',
                    deptName: 'Product department'
                }],
                // Table's source data
                data1: [{
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: 'Product department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    }, {
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: 'Development Department'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: 'Test department'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: 'Product department'
                    }
                ],
                // Data per page of table
                data2: [],
                // Whether the table border is displayed
                showBorder: false,
                // Table whether zebra stripes are displayed
                showStripe: false,
                // Whether the table header is displayed
                showHeader: true,
                // Whether the table index is displayed
                showIndex: true,
                // Whether the table multi selection box is displayed
                showCheckbox: false,
                // Whether the table scroll bar is on
                fixedHeader: false,
                // Change table size
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // Change the current page number and obtain the data owned by the current page number
                this.currentPage = index
                // Note that it cannot be used directly here = Assignment. Use = After (pointing to the same address), modify data2 It will be modified at the same time data1
                this.data2 = [].concat(this.data1.slice((index - 1) * this.pageSize, index * this.pageSize))
            },
            show(index) {
                // Pop up a modal box to show the information of a piece of data
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {index: index})
            },
            create() {
                // Used to add a message
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(index) {
                // Delete a piece of data (delete source data)
                this.data1.splice((this.currentPage - 1) * 10 + index, 1)
            },
            changePageSize(index) {
                // Change the number of items displayed per page
                this.$Message.info({
                    content: 'The number of items displayed on the current page is modified to: ' + index + 'strip/page'
                })
                // After the change, jump to the home page and refresh the list
                this.currentPage = 1
                this.pageSize = index
                this.changePage(this.currentPage)
            },
            okEditor () {
                if (this.createOrEditor) {
                    // Edit action,Modifying data
                    this.data1.splice((this.currentPage - 1) * 10 + this.empInfo.index, 1, this.empInfo)
                } else {
                    // Add operation, modify data
                    this.data1.push(Object.assign({}, this.empInfo))
                }
                this.empInfo = {}
            },
            cancelEditor () {
                // Cancel editing
                this.$Message.info({
                    content: 'Operation cancelled'
                })
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // by true Add an index column to the first
                    this.tableColumns1.unshift({
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // by false If there is an index column in the first part, the column will be removed
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // by true Add a multi check box column in the first part,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // by false If there is more than one box column, remove it
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            data1() {
                // When the list data changes (such as deleting some data), a refresh of the list will be triggered
                if (!this.createOrEditor) {
                    // To add data, go to the last page
                    this.changePage(Math.ceil(this.data1.length / this.pageSize))
                } else {
                    this.changePage(this.currentPage)
                }
            }
        },
        mounted() {
            // When the page is loaded, the first refresh of the list is triggered
            this.changePage(this.currentPage)
            // No need to use this.getAllEmps(),Direct use getAllEmps() that will do
            getAllEmps({
                pageNum: this.currentPage,
                pageSize: this.pageSize
            }).then((res) => {
          console.log(res)
        }) } }
</script>

 

2. Call the interface and interact with the background

(1) interface details

[Get all emp Information (pagination query)
GET                                            param
http://localhost:9000/crud/emps/{pageNum}      pageSize

[Get information about an employee (useless)
GET
http://localhost:9000/crud/emp/{id}

[Delete an employee's information]
DELETE
http://localhost:9000/crud/emp/{id}

[Insert a piece of data]
POST
http://localhost:9000/crud/emp                Employee

[Update a piece of data]
PUT
http://localhost:9000/crud/emp/{id}           Employee

[Get department information]
GET
http://localhost:9000/crud/depts

 

(2) complete code

Code structure screenshot:

 

 

 

[main.js]
import Vue from 'vue'
import App from './App.vue'
import ViewUI from 'view-design'
import 'view-design/dist/styles/iview.css'
import Axios from 'axios'

Vue.config.productionTip = false
Vue.use(ViewUI)
Vue.prototype.$axios = Axios
Axios.defaults.baseURL = '/api'

new Vue({
  render: h => h(App),
}).$mount('#app')


[App.vue]
<template>
    <div style="width: 1200px; margin: 0 auto;" class="layout">
        <Layout>
            <header>
                <row>
                    <Divider orientation="left">
                        <h1>Employee list</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><Button type="primary" icon="md-add" @click="create">Add to</Button></i-col>
                    <i-col style="margin-right: 5px"><Button type="success" icon="md-settings" @click="setUp = true">Set up</Button></i-col>
                </row>
            </header>
            <Content>
                <Table :data="data2" :columns="tableColumns1" :stripe="showStripe" :border="showBorder" :showHeader="showHeader" :size="tableSize" :height="fixedHeader ? 250 : ''">
                    <template slot-scope="{ row }" slot="name">
                        <strong>{{ row.name }}</strong>
                    </template>
                    <template slot-scope="{ row, index }" slot="action">
                        <Button type="primary" size="small" style="margin-right: 5px" @click="show(index)" icon="ios-create-outline">edit</Button>
                        <Button type="error" size="small" @click="remove(row, index)" icon="ios-trash">delete</Button>
                    </template>
                </Table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current Set the currently selected page,pageSize Set the number of displayed data per page-->
                        <Page :total="total" :pageSize="pageSize" :current="currentPage" @on-change="changePage" show-sizer show-elevator show-total @on-page-size-change="changePageSize"></Page>
                    </div>
                </div>
            </Content>
        </Layout>

        <Drawer title="Set up" :closable="true" :mask="false" v-model="setUp">
            <div style="margin: 10px">
                Table Setting<br>
                <i-switch v-model="showBorder" style="margin-right: 5px"></i-switch>Display border<br>
                <i-switch v-model="showStripe" style="margin-right: 5px"></i-switch>Display stripe<br>
                <i-switch v-model="showIndex" style="margin-right: 5px"></i-switch>Display index<br>
                <i-switch v-model="showCheckbox" style="margin-right: 5px"></i-switch>Display multi choice<br>
                <i-switch v-model="showHeader" style="margin-right: 5px"></i-switch>Display header<br>
                <i-switch v-model="fixedHeader" style="margin-right: 5px"></i-switch>Table scrolling<br>
                <br><br>

                Table size
                <Select v-model="tableSize" style="width:200px">
                    <Option value="large">large</Option>
                    <Option value="default">medium(default)</Option>
                    <Option value="small">small</Option>
                </Select>
            </div>
        </Drawer>

        <Modal v-model="empModal" title="Emp Info" @on-ok="okEditor" @on-cancel="cancelEditor">
            <Form :label-width="80">
                <FormItem label="Name:">
                    <Input v-model="empInfo.name" placeholder="Name..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Salary:">
                    <Input v-model="empInfo.salary" placeholder="Salary..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Age:">
                    <Input v-model="empInfo.age" placeholder="Age..." style="width: 300px;" />
                </FormItem>
                <FormItem label="Email:">
                    <Input v-model="empInfo.email" placeholder="Email..." style="width: 300px;" />
                </FormItem>
                <FormItem label="DeptName:">
                    <Select v-model="empInfo.deptid">
                        <Option v-for="(item, index) in dept" :key="index" :value="item.deptid"> {{item.deptname}} </Option>
                    </Select>
                </FormItem>
            </Form>
        </Modal>
    </div>
</template>
<script>
    import {
        getAllEmps,
        getEmp,
        deleteEmp,
        updateEmp,
        insertEmp,
        getDeptName
    } from './api/api.js'
    export default {
        data() {
            return {
                // Save the total data of the list
                total: 0,
                // Add and edit reuse modal Box, false To add, true Editors
                createOrEditor: false,
                // Open employee information box
                empModal: false,
                // Information used to save an employee
                empInfo: {},
                // Open settings or not
                setUp: false,
                // Current page number
                currentPage: 1,
                // Number of data per page
                pageSize: 10,
                // Column of tables
                tableColumns1: [{
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    }, {
                        title: 'Name',
                        slot: 'name'
                    }, {
                        title: 'Salary',
                        key: 'salary',
                        sortable: true
                    },
                    {
                        title: 'Age',
                        key: 'age',
                        sortable: true
                    },
                    {
                        title: 'Email',
                        key: 'email'
                    }, {
                        title: 'DeptName',
                        key: 'deptName'
                    },
                    {
                        title: 'Action',
                        slot: 'action',
                        width: 200,
                        align: 'center'
                    }
                ],
                dept: [],
                // Data per page of table
                data2: [],
                // Whether the table border is displayed
                showBorder: false,
                // Table whether zebra stripes are displayed
                showStripe: false,
                // Whether the table header is displayed
                showHeader: true,
                // Whether the table index is displayed
                showIndex: true,
                // Whether the table multi selection box is displayed
                showCheckbox: false,
                // Whether the table scroll bar is on
                fixedHeader: false,
                // Change table size
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // Change the current page number and obtain the data owned by the current page number
                this.currentPage = index

                // Obtain emps data,Paging query
                getAllEmps({
                    pageNum: this.currentPage,
                    pageSize: this.pageSize
                }).then((res) => {
                    if (res.data.success) {
                        // Save acquired emp list
                        this.data2 = res.data.pageInfo.list
                        // Total number of saved acquired data
                        this.total = res.data.pageInfo.total
                    }
                    this.noticeType(res.data.level, res.data.messages)
                }).catch((res) => {
                    this.noticeType()
                })
            },
            show(index) {
                // Pop up a modal box to show the information of a piece of data
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {
                    index: index
                })
            },
            create() {
                // Used to add a message
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(row, index) {
                this.$Modal.confirm({
                    title: 'delete',
                    content: '<p>Delete current data or not</p>',
                    onOk: () => {
                        // Delete an employee's data
                        deleteEmp({
                            id: row.id
                        }).then((res) => {
                            if (res.data.success) {
                                this.changePage(this.currentPage)
                            }
                            this.noticeType(res.data.level, res.data.messages)
                        }).catch((res) => {
                            this.noticeType()
                        })
                    },
                    onCancel: () => {
                        this.$Message.info('Cancel delete')
                    },
                    okText: 'OK',
                    cancelText: 'Cancel'
                })
            },
            changePageSize(index) {
                // Change the number of items displayed per page
                this.$Message.info({
                    content: 'The number of items displayed on the current page is modified to: ' + index + 'strip/page'
                })
                // After the change, jump to the home page and refresh the list
                this.pageSize = index
                if(this.currentPage === 1) {
                    this.changePage(this.currentPage)
                    return
                }
                this.currentPage = 1
            },
            okEditor() {
                if (this.createOrEditor) {
                    // Update data for an employee
                    const that = this
                    updateEmp(this.empInfo).then((res) => {
                        if (res.data.success) {
                            this.changePage(this.currentPage)
                        }
                        this.noticeType(res.data.level, res.data.messages)
                    }).catch((res) => {
                        this.noticeType()
                    })
                } else {
                    // Add an employee
                    this.empInfo = Object.assign({}, this.empInfo, {
                        id: null
                    })
                    insertEmp(this.empInfo).then((res) => {
                        if (res.data.success) {
                            this.changePage(Math.ceil((this.total + 1) / this.pageSize))
                        }
                        this.noticeType(res.data.level, res.data.messages)
                    }).catch((res) => {
                        this.noticeType()
                    })
                }
                this.empInfo = {}
            },
            cancelEditor() {
                // Cancel editing
                this.$Message.info({
                    content: 'Operation cancelled'
                })
            },
            noticeType(type, messages) {
                switch (type) {
                    case 'info':
                        this.$Notice.success({
                            title: messages.join('\n'),
                            duration: 2
                        })
                        break
                    case 'error':
                        this.$Notice.error({
                            title: messages.join('\n'),
                            duration: 2
                        })
                        break
                    default:
                        this.$Notice.error({
                            title: 'System exception',
                            duration: 2
                        })
                        break
                }
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // by true Add an index column to the first
                    this.tableColumns1.unshift({
                        // To have automatic indexing when paging, set the type = "index2",And use render To return the index value
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // by false If there is an index column in the first part, the column will be removed
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // by true Add a multi check box column in the first part,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // by false If there is more than one box column, remove it
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            empModal(newVal) {
                // If the mode box is opened, an operation to obtain department information will be triggered
                if (newVal) {
                    // Get department information
                    getDeptName().then((res) => {
                        if (res.data.success) {
                            // Use Object.assign When assigning a value to an object, the following method is recommended to create a new object.
                            // If you still use the same object, such as this.dept = Object.assign(this.dept, res.data.departments),vue It may not be able to monitor its changes.
                            this.dept = Object.assign({}, this.dept, res.data.departments)
                        }
                    }).catch((res) => {
                        this.noticeType()
                    })
                }
            }
        },
        mounted() {
            // When the page is loaded, the first refresh of the list is triggered
            this.changePage(this.currentPage)
        }
    }
</script>



[api.js]
import Axios from 'axios'

/**
 * Get emps data, page by page query
 * @param {Object} params Paging parameter (pageNum current page number, pageSize total data per page) 
 */
export function getAllEmps(params) {
    return new Promise((resolve, reject) => {
        Axios.get('/emps/' + params.pageNum, {
            params
        }).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * Get the data of an employee
 * @param {Object} params Parameter is employee's id
 */
export function getEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.get('/emp/' + params.id).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * Delete an employee's data
 * @param {Object} params Parameter is employee's id
 */
export function deleteEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.delete('/emp/' + params.id).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * Update data for an employee
 * @param {Object} params The parameter is employee id and employee data
 */
export function updateEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.put('/emp/' + params.id, params).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * Add an employee
 * @param {Object} params The parameter is employee id and employee data
 */
export function insertEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.post('/emp', params).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * Get department information
 * @param {Object} params 
 */
export function getDeptName(params) {
    return new Promise((resolve, reject) => {
        Axios.get('/depts').then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}


[vue.config.js]
module.exports = {
    devServer: {
        proxy: {
            '/api': {
                // This is written to replace / api with http://localhost:9000/crud
                target: 'http://localhost:9000/crud/',
                // Cross domain allowed
                changeOrigin: true,
                ws: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
}


[package.json]
{
  "name": "ssm_crud_front",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "axios": "^0.19.0",
    "core-js": "^3.3.2",
    "view-design": "^4.0.2",
    "vue": "^2.6.10"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.0.0",
    "@vue/cli-plugin-eslint": "^4.0.0",
    "@vue/cli-service": "^4.0.0",
    "babel-eslint": "^10.0.3",
    "eslint": "^5.16.0",
    "eslint-plugin-vue": "^5.0.0",
    "vue-template-compiler": "^2.6.10"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "rules": {
      "generator-star-spacing": "off",
      "no-tabs": "off",
      "no-unused-vars": "off",
      "no-console": "off",
      "no-irregular-whitespace": "off",
      "no-debugger": "off"
    },
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
  "postcss": {
    "plugins": {
      "autoprefixer": {}
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

 

 

 

Keywords: Java Spring xml Mybatis Vue

Added by ErikTheViking on Thu, 12 Dec 2019 11:39:06 +0200