SSM + VUE 實現簡單的 CRUD


一、項目分析

1、需求

(1)使用 ssm + vue 實現一個crud(數據庫增刪改查)的簡單實現。
(2)前后端分離,前端頁面展示+后台管理。

 

2、技術點

(1)基礎框架: SSM(Spring,SpringMVC,Mybatis)
(2)數據庫: Mysql
(3)前端: UI框架 iView + vue
(4)項目依賴管理: maven
(5)分頁: pagehelper
(6)逆向工程: Mybatis Generator
(7)開發工具:IDEA + Chrome + HBuilder X

 

二、項目地址、截圖

1、項目地址

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

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

2、項目截圖

(1)初始界面(查數據)

  Step1:初始化界面(獲取第一頁數據)

 

 

 

  Step2:可以設置每頁數據的條數,如下,設置 20條/頁

 

 

 

  Step3:點擊設置按鈕,可以設置表格樣式。

 

 

 

 

 

   Step4:切換頁面,數據刷新(根據當前頁碼向后台發送請求,獲取數據)

 

 

 

(2)修改數據

  Step1:點擊編輯按鈕(如下,選擇第一條數據,展示所選擇的數據。)

 

 

   Step2:修改數據

 

 

   Step3:修改后,展示數據

 

 

 

(3)刪除數據

  Step1:點擊刪除按鈕(比如第一條數據),會彈出一個提示框

 

 

   Step2:選擇 Ok,刪除該數據

 

 

 

(3)添加數據

  Step1:點擊添加按鈕

 

 

   Step2:填寫信息

 

 

   Step3:點擊確定,插入數據,並跳轉到最后一頁

 

 

 

 

三、后端項目環境搭建

  搭建后的整個文件結構:

 

 

 

1、使用IDEA創建一個maven工程。

  可以參考 https://www.cnblogs.com/l-y-h/p/11454933.html

2、引入項目依賴的jar包(配置依賴信息)。

  需要配置Spring,SpringMVC,mybatis,數據庫連接池,數據庫驅動包,以及其他的jar包,比如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 與 mybatis 的整合包 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <!-- 數據庫連接池,c3p0 --> <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.4</version> </dependency> <!-- mysql驅動包 --> <!-- 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> <!-- 逆向工程所需的依賴信息 --> <!-- 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 分頁插件 --> <!-- 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、配置ssm整合的文件(詳細過程后續展開)。

  web.xml,spring,springmvc,mybatis。

4、官方文檔:

  Spring:http://spring.io/docs

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

  分頁組件的使用: https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/en/HowToUse.md

 

三、(3.1)SSM基本配置--配置web.xml

1、配置Spring容器

  用於獲取 Spring 配置文件(applicationContext.xml) 的讀取位置。
  <context-param>直接配置在web.xml的<web-app>標簽中,屬於上下文參數,在整個web應用中都可以使用。它是全局的,因此存放在servletContext對象中(即application對象)。通過getServletContext().getInitParameter("contextParam")的方式可以獲取。

【在web.xml中配置】

<!-- step1: 配置全局的參數,啟動Spring容器 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <!-- 若沒有提供值,默認會去找/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、配置SpringMVC的前端控制器

  用於攔截請求,並指定Spring MVC配置文件的讀取位置。

  <init-parm>配置在<servlet>標簽中,用來初始化當前的Servlet的。屬於當前Servlet的配置,因此存放在servletConfig對象(servlet對象)中。

  通過getServletConfig().getInitParameter("initParam")的方式可以獲取。

【在web.xml中配置】

<!-- step2: 配置SpringMVC的前端控制器,用於攔截所有的請求  -->
<servlet>
    <servlet-name>springmvcDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>
        <param-name>contextConfigLocation</param-name>
        <!-- 若沒有提供值,默認會去找WEB-INF/*-servlet.xml。 -->
        <param-value>classpath:dispatcher-servlet.xml</param-value>
    </init-param>
    <!-- 啟動優先級,數值越小優先級越大 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvcDispatcherServlet</servlet-name>
    <!-- 將DispatcherServlet請求映射配置為"/",則Spring MVC將捕獲Web容器所有的請求,包括靜態資源的請求 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

注:

  spring框架在加載web配置文件的時候。首先加載的是context-param配置的內容,而並不會去初始化servlet。只有進行了網站的跳轉,經過DispatcherServlet的時候,才會初始化servlet,從而加載init-param中的內容。

 

3、配置解決亂碼問題的過濾器

  用於解決亂碼問題。

【在web.xml中配置】

<!-- step3: characterEncodingFilter字符編碼過濾器,放在所有過濾器的前面 -->
<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <!--要使用的字符集,一般我們使用UTF-8(保險起見UTF-8最好)-->
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <!--是否強制設置request的編碼為encoding,默認false,不建議更改-->
        <param-name>forceRequestEncoding</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <!--是否強制設置response的編碼為encoding,建議設置為true-->
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <!--這里不能留空或者直接寫 ' / ' ,否則可能不起作用-->
    <url-pattern>/*</url-pattern>
</filter-mapping>

 

4、配置Rest風格的URI

  由於瀏覽器form表單只支持GET與POST請求,而DELETE、PUT等method並不支持,spring3.0添加了一個過濾器(HiddenHttpMethodFilter),可以將這些請求轉換為標准的http方法,使得支持GET、POST、PUT與DELETE請求。

【在web.xml中配置】

<!-- step4: 配置過濾器,將post請求轉為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.xml 的加載順序是:[context-param -> listener -> filter -> servlet -> spring] ,而同類型節點之間的實際程序調用的時候的順序是根據對應的 mapping 的順序進行調用的。

 

5、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: 配置全局的參數,啟動Spring容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- 若沒有提供值,默認會去找/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: 配置SpringMVC的前端控制器,用於攔截所有的請求  -->
    <servlet>
        <servlet-name>springmvcDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 若沒有提供值,默認會去找WEB-INF/*-servlet.xml。 -->
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
        <!-- 啟動優先級,數值越小優先級越大 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvcDispatcherServlet</servlet-name>
        <!-- 將DispatcherServlet請求映射配置為"/",則Spring MVC將捕獲Web容器所有的請求,包括靜態資源的請求 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- step3: characterEncodingFilter字符編碼過濾器,放在所有過濾器的前面 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <!--要使用的字符集,一般我們使用UTF-8(保險起見UTF-8最好)-->
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <!--是否強制設置request的編碼為encoding,默認false,不建議更改-->
            <param-name>forceRequestEncoding</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <!--是否強制設置response的編碼為encoding,建議設置為true-->
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!--這里不能留空或者直接寫 ' / ' ,否則可能不起作用-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- step4: 配置過濾器,將post請求轉為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.2)配置SpringMVC--dispatcher-servlet.xml

1、配置組件掃描方式

  用於獲取相關組件。 一般在SpringMVC的配置里,只掃描Controller層,Spring配置中掃描所有包,但是排除Controller層。

【在dispatcher-servlet.xml中配置】

<!-- step1: 配置Controller掃描方式 -->
<!-- 使用組件掃描的方式可以一次掃描多個Controller,只需指定包路徑即可 -->
<context:component-scan base-package="com.lyh.ssm.crud" use-default-filters="false">
    <!-- 一般在SpringMVC的配置里,只掃描Controller層,Spring配置中掃描所有包,但是排除Controller層。
    context:include-filter要注意,如果base-package掃描的不是最終包,那么其他包還是會掃描、加載,如果在SpringMVC的配置中這么做,會導致Spring不能處理事務,
    所以此時需要在<context:component-scan>標簽上,增加use-default-filters="false",就是真的只掃描context:include-filter包括的內容-->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>



<!-- 配置單個Controller的方式(某些特殊的情況可以使用),需要指定Controller的全限定名 -->
<!-- <bean name="/get" class="com.wxisme.ssm.controller.Controller1"/> -->

 

2、配置視圖解析器

  當設置視圖名時,會自動添加前綴與后綴。

【在dispatcher-servlet.xml中配置】

<!-- step2: 配置視圖解析器,設置視圖名時,會自動添加上前綴與后綴 -->
<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/"/><!--設置JSP文件的目錄位置-->
    <property name="suffix" value=".jsp"/>
</bean>

 

3、配置請求處理(標准配置一)

  將DispatcherServlet請求映射配置為"/",則Spring MVC將捕獲Web容器所有的請求(包括靜態資源的請求),Spring MVC會將它們當成一個普通請求處理,因此找不到對應處理器將導致錯誤。所以為了使Spring框架能夠捕獲所有URL的請求,同時又將靜態資源的請求轉由Web容器處理,在將DispatcherServlet的請求映射配置為"/"前提下,使用<mvc:default-servlet-handler />,可以將靜態請求交給服務器處理。

【在dispatcher-servlet.xml中配置】

<!-- 會在Spring MVC上下文中定義一個org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它會像一個檢查員,對進入DispatcherServlet的URL進行篩查,如果發現是靜態資源的請求,就將該請求轉由Web應用服務器默認的Servlet處理,如果不是靜態資源的請求,才由DispatcherServlet繼續處理。 -->
<mvc:default-servlet-handler />

 

4、配置注解的處理器映射器和處理器適配器(標准配置二)

  <mvc:annotation-driven />簡化了注解配置,且提供了一些高級功能,比如支持使用@Valid對javaBean進行JSR-303驗證、支持使用@RequestBody、@ResponseBody。

【在dispatcher-servlet.xml中配置】
【方式一:】
<!-- 配置注解的處理器映射器和處理器適配器(簡化配置) -->
<mvc:annotation-driven />

【方式二:】
<!-- 注解的處理器適配器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
<!-- 注解的處理器映射器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->

 

5、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: 配置Controller掃描方式 -->
    <!-- 使用組件掃描的方式可以一次掃描多個Controller,只需指定包路徑即可 -->
    <context:component-scan base-package="com.lyh.ssm.crud" use-default-filters="false">
        <!-- 一般在SpringMVC的配置里,只掃描Controller層,Spring配置中掃描所有包,但是排除Controller層。
        context:include-filter要注意,如果base-package掃描的不是最終包,那么其他包還是會掃描、加載,如果在SpringMVC的配置中這么做,會導致Spring不能處理事務,
        所以此時需要在<context:component-scan>標簽上,增加use-default-filters="false",就是真的只掃描context:include-filter包括的內容-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- step2: 配置視圖解析器 -->
    <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"/><!--設置JSP文件的目錄位置-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- step3: 標准配置 -->
    <!-- 將springmvc不能處理的請求交給 spring 容器處理 -->
    <mvc:default-servlet-handler/>
    <!-- 簡化注解配置,並提供更高級的功能 -->
    <mvc:annotation-driven />
</beans>

 

三、(3.3)配置Spring--applicationContext.xml

1、配置組件掃描方式

  用於獲取相關組件 ,一般在Spring配置文件中掃描所有包,但是排除Controller層。

【在applicationContext.xml中配置】

<!-- step1: 配置包掃描方式。掃描所有包,但是排除Controller層 -->
<context:component-scan base-package="com.lyh.ssm.crud">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

 

2、配置數據庫連接池

  用於數據庫操作。

【方式一:直接填寫連接參數】
【在applicationContext.xml中配置】
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!--注入屬性-->
    <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>

【方式二:通過properties文件的方式獲取連接參數】
【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

【在applicationContext.xml中配置】
<!-- 引入properties文件 -->
<context:property-placeholder location="classpath:dbconfig.properties" />

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!--注入屬性-->
    <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>

 

三、(3.4)Spring和MyBatis整合配置--applicationContext.xml

  jar包由MyBatis提供。

1、配置sqlSessionFactory 

【在applicationContext.xml中配置】

<!-- step3: spring 與 mybatis 整合 -->
<!-- 配置sqlSessionFactory,需要引入 mybatis-spring 包 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 加載Mybatis全局配置文件 -->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>

    <!-- 數據庫連接池 -->
    <property name="dataSource" ref="dataSource"/>

    <!-- 配置mapper文件位置,掃描映射文件 -->
    <property name="mapperLocations" value="classpath:mappers/*.xml"/>
</bean>

2、配置批量執行的sqlSession(可選操作)

【在applicationContext.xml中配置】

<!-- step4: 配置批量執行的sqlSession(可選操作) -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <constructor-arg name="executorType" value="BATCH"/>
</bean>

 

3、配置mapper掃描器

【在applicationContext.xml中配置】

<!-- step5: 配置mapper掃描器,將其加入到ioc容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 掃描包路徑,如果需要掃描多個包中間用半角逗號隔開 -->
    <property name="basePackage" value="com.lyh.ssm.crud.dao"></property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

 

4、配置事務控制與切面(可選)

【在applicationContext.xml中配置】

<!-- step6: 配置事務控制 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 配置數據源 -->
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 配置事務通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!-- 傳播行為 -->
        <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>

<!-- 配置aop -->
<aop:config>
    <!-- 配置事務增強,指定切點表達式,第一個*表示返回任意類型,第二個*表示任意方法,(..)表示任意數量和類型的參數-->
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lyh.ssm.crud.service..*(..))"/>
</aop:config>

 

5、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: 配置包掃描方式。掃描所有包,但是排除Controller層 -->
    <context:component-scan base-package="com.lyh.ssm.crud">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- step2: 配置數據庫連接信息 -->
    <!-- 引入properties文件 -->
    <context:property-placeholder location="classpath:db.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--注入屬性-->
        <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 與 mybatis 整合 -->
    <!-- 配置sqlSessionFactory,需要引入 mybatis-spring 包 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 加載Mybatis全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>

        <!-- 數據庫連接池 -->
        <property name="dataSource" ref="dataSource"/>

        <!-- 配置mapper文件位置,掃描映射文件 -->
        <property name="mapperLocations" value="classpath:mappers/*.xml"/>
    </bean>

    <!-- step4: 配置批量執行的sqlSession(可選操作) -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        <constructor-arg name="executorType" value="BATCH"/>
    </bean>

    <!-- step5: 配置mapper掃描器,將其加入到ioc容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 掃描包路徑,如果需要掃描多個包中間用半角逗號隔開 -->
        <property name="basePackage" value="com.lyh.ssm.crud.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!-- step6: 配置事務控制 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 配置數據源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置事務通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 傳播行為 -->
            <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>

    <!-- 配置aop -->
    <aop:config>
        <!-- 配置事務增強,指定切點表達式,第一個*表示返回任意類型,第二個*表示任意方法,(..)表示任意數量和類型的參數-->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lyh.ssm.crud.service..*(..))"/>
    </aop:config>
</beans>

 

三、(3.5)Mybatis配置 -- mybatis-config.xml

1、配置全局參數

【在mybatis-config.xml中配置】

<settings>
    <!-- 開啟駝峰命名規則 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

 

2、使用分頁插件(pagehelper)

【在mybatis-config.xml中配置】

<plugins>
   <!-- 使用分頁插件 -->
   <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

 

3、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>
        <!-- 開啟駝峰命名規則 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <plugins>
        <!-- 使用分頁插件 -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
</configuration>

 

四、逆向工程

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

1、配置文件 -- 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">
        <!-- 清除注釋信息 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!-- step1: 配置數據庫連接信息 -->
        <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: 指定java bean生成的位置
            targetProject 指的是 哪個項目
            targetPackage 指的是 項目中的路徑
        -->
        <javaModelGenerator targetPackage="com.lyh.ssm.crud.bean" targetProject=".\src">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- step3:指定sql映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="com.lyh.ssm.crud.mapper" targetProject=".\src">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!-- step4: 指定接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.lyh.ssm.crud.dao" targetProject=".\src">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!-- step5: 指定表的生成策略
            tableName 指定表名
            domainObjectName 指定表對應的 實體類的名字
        -->
        <table tableName="emp" domainObjectName="Employee"></table>
        <table tableName="dept" domainObjectName="Department"></table>
    </context>
</generatorConfiguration>

 

2、執行類 -- 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);
    }
}

 

注:

  文件生成后,位置可能不對。需手動將文件復制到相應位置。

 

 

五、數據庫 (mysql 1.8)

1、創建數據表

emp
    -- 創建一個 emp 表,其中 id 為主鍵且自增。
    CREATE TABLE emp(
        id int primary key auto_increment,
        name varchar(50),
        salary double,
        age int,
        email varchar(50)
    );

dept
    -- 創建一個 dept 表,其中 deptId 為自增主鍵
    CREATE TABLE dept(
        deptId INT(11) PRIMARY KEY AUTO_INCREMENT,
        deptName VARCHAR(255)
    );
    
    -- 給 emp 表增加一個列
    ALTER TABLE emp ADD COLUMN deptId INT(11);
    
    -- 並將 emp 中該列作為外鍵關聯到 dept 的主鍵
    ALTER TABLE emp ADD CONSTRAINT fk_emp_dept FOREIGN KEY(deptId) REFERENCES dept(deptId);

 

2、插入一些數據(可選操作)

dept
    INSERT INTO dept(deptId, deptName) VALUES(1, '開發部');
    INSERT INTO dept(deptId, deptName) VALUES(2, '測試部');
    INSERT INTO dept(deptId, deptName) VALUES(3, '產品部');

emp(id自增,給其插個 null 即可)
    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、測試后台代碼與數據庫的交互(可選操作)

【在applicationContext.xml中配置 批量執行的 sqlSession】
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <constructor-arg name="executorType" value="BATCH"/>
</bean>


【測試類 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, "開發部"));
        departmentMapper.insertSelective(new Department(null, "測試部"));
    }

    @Test
    public void testEmp() {
        // 批量執行 sql 語句
        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));
        }
    }
}

 

 

 

六、后端代碼

1、文件結構

 

 

 

 

2、代碼

【com.lyh.ssm.crud.model.BaseModel】

package com.lyh.ssm.crud.model; import java.util.ArrayList; import java.util.List; /** * 基礎返回類型, * messages 用於保存返回的信息 * level 用於保存信息的級別 * Level 為枚舉類型 */ 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; /** * 員工返回信息類,用於返回員工信息 */ 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; /** * 獲取分頁的數據 * @param pageNum 獲取第幾頁的數據 * @param pageSize 返回數據的條數 * @return 返回數據 */ @GetMapping("/emps/{pageNum}") public EmpPageModel getAllEmp(@PathVariable Integer pageNum, @RequestParam Integer pageSize) { // step1:引入分頁插件(PageHelper) // step2:每次查詢前,設置查詢的頁面以及查詢的條數,每次獲取5條數據 PageHelper.startPage(pageNum, pageSize); // step3:執行分頁查詢 List<Employee> employeeList = empService.getAllEmp(); // step4:包裝查詢后的數據 PageInfo pageInfo = new PageInfo(employeeList); EmpPageModel empPageModel = new EmpPageModel(); if (employeeList.size() <= 0) { empPageModel.addMessage("獲取分頁數據失敗"); empPageModel.setSuccess(false); empPageModel.setLevel(BaseModel.Level.error); return empPageModel; } empPageModel.addMessage("獲取分頁數據成功"); empPageModel.setSuccess(true); empPageModel.setLevel(BaseModel.Level.info); empPageModel.setPageInfo(pageInfo); return empPageModel; } /** * 獲取某個員工的信息 * REST -- GET * @param id 員工的id * @return 返回數據 */ @GetMapping("/emp/{id}") public EmpModel getEmpById(@PathVariable Integer id) { EmpModel empModel = new EmpModel(); if (empService.getEmpById(id) == null) { empModel.addMessage("獲取員工信息失敗"); empModel.setSuccess(false); empModel.setLevel(BaseModel.Level.error); return empModel; } empModel.addMessage("獲取員工信息成功"); empModel.setSuccess(true); empModel.setLevel(BaseModel.Level.info); empModel.addEmployee(empService.getEmpById(id)); return empModel; } /** * 刪除某個員工的信息 * REST -- DELETE * @param id 員工的id * @return 返回數據 */ @RequestMapping(value = "/emp/{id}", method = RequestMethod.DELETE) public BaseModel deleteEmpById(@PathVariable Integer id) { BaseModel baseModel = new BaseModel(); if (empService.deleteEmpById(id) != 0) { baseModel.addMessage("刪除員工信息成功"); baseModel.setSuccess(true); baseModel.setLevel(BaseModel.Level.info); return baseModel; } baseModel.addMessage("刪除員工信息失敗"); baseModel.setSuccess(false); baseModel.setLevel(BaseModel.Level.error); return baseModel; } /** * 向員工表中插入員工信息 * REST -- POST * 使用 @RequestBody 需注意,前台傳遞的參數名要與 Employee 里的參數名對應,否則接收不到值 * @param employee 員工信息 * @return 返回數據 */ @PostMapping("/emp") public BaseModel insertEmp(@RequestBody Employee employee) { BaseModel baseModel = new BaseModel(); if (empService.insertEmp(employee) != 0) { baseModel.addMessage("插入員工信息成功"); baseModel.setSuccess(true); baseModel.setLevel(BaseModel.Level.info); return baseModel; } baseModel.addMessage("插入員工信息失敗"); baseModel.setSuccess(false); baseModel.setLevel(BaseModel.Level.error); return baseModel; } /** * 更新員工信息 * REST -- PUT * @param employee 員工信息 * @return 返回數據 */ @RequestMapping(value = "/emp/{id}", method = RequestMethod.PUT) public BaseModel updateEmp(@RequestBody Employee employee) { BaseModel baseModel = new BaseModel(); if (empService.updateEmp(employee) != 0) { baseModel.addMessage("更新員工信息成功"); baseModel.setSuccess(true); baseModel.setLevel(BaseModel.Level.info); return baseModel; } baseModel.addMessage("更新員工信息失敗"); 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("獲取部門信息失敗"); deptModel.setSuccess(false); deptModel.setLevel(BaseModel.Level.error); return deptModel; } deptModel.addMessage("獲取部門信息成功"); 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; /** * 獲取某個員工的信息 * * @param id 某個員工的id * @return 某個員工的信息 */ public Employee getEmpById(Integer id) { return employeeMapper.selectByPrimaryKey(id); } /** * 獲取所有員工的信息 * * @return 所有員工的信息 */ public List<Employee> getAllEmp() { return employeeMapper.selectAll(); } /** * 插入某個員工的信息 * * @param emp 某員工的信息 * @return 返回插入影響的行數 */ public Integer insertEmp(Employee emp) { return employeeMapper.insertSelective(emp); } /** * 刪除某個員工的信息 * * @param id 員工的id * @return 返回刪除影響的行數 */ public Integer deleteEmpById(Integer id) { return employeeMapper.deleteByPrimaryKey(id); } /** * 更新某個員工的信息 * @param employee 員工信息 * @return 返回修改影響的行數 */ 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 添加方法】 <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>

 

七、前端代碼--靜態頁面

1、非 template/render 模式下

此時 部分組件名前 需加前綴 i- 才可使用。

比如:

  Button  -->  i-button

  Table    -->  i-table

  Select  -->  i-select

  Option  -->  i-option

  Form    -->  i-form

  FormItem  -->  form-item

【非 template/render 模式下】

<!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>員工列表</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><i-button type="primary" icon="md-add" @click="create">添加</i-button></i-col>
                    <i-col style="margin-right: 5px"><i-button type="success" icon="md-settings" @click="setUp = true">設置</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">編輯</i-button>
                        <i-button type="error" size="small" @click="remove(index)" icon="ios-trash">刪除</i-button>
                    </template>
                </i-table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current 設置當前選中頁,pageSize 設置每頁顯示數據的條數-->
                        <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 {
                // 添加與編輯復用 modal 框,false為添加,true為編輯
                createOrEditor: false,
                // 是否打開員工信息框
                empModal: false,
                // 用於保存一個員工的信息
                empInfo: {},
                // 是否打開設置
                setUp: false,
                // 當前頁碼
                currentPage: 1,
                // 每頁數據的條數
                pageSize: 10,
                // 表格的列
                tableColumns1: [{
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        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: '開發部'
                },{
                    deptId: '2',
                    deptName: '測試部'
                },{
                    deptId: '3',
                    deptName: '產品部'
                }],
                // 表格的源數據
                data1: [{
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: '產品部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    }, {
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: '產品部'
                    }
                ],
                // 表格每頁的數據
                data2: [],
                // 表格邊框是否顯示
                showBorder: false,
                // 表格斑馬紋是否顯示
                showStripe: false,
                // 表格頭是否顯示
                showHeader: true,
                // 表格索引是否顯示
                showIndex: true,
                // 表格多選框是否顯示
                showCheckbox: false,
                // 表格滾動條是否開啟
                fixedHeader: false,
                // 改變表格大小
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // 改變當前的頁碼,並獲取當前頁碼所擁有的數據
                this.currentPage = index
                // 注意,此處不能直接用 = 賦值。使用 = 后(指向的地址相同),修改 data2 的同時會修改 data1
                this.data2 = [].concat(this.data1.slice((index - 1) * this.pageSize, index * this.pageSize))
            },
            show(index) {
                // 彈出一個模態框,用於展示某條數據的信息
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {index: index})
            },
            create() {
                // 用於添加一條信息
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(index) {
                // 刪除某條數據(刪除源數據)
                this.data1.splice((this.currentPage - 1) * 10 + index, 1)
            },
            changePageSize(index) {
                // 改變每頁顯示的條數
                this.$Message.info({
                    content: '當前頁面顯示條數修改為: ' + index + '條/頁'
                })
                // 改變后,跳轉到首頁,並刷新列表
                this.currentPage = 1
                this.pageSize = index
                this.changePage(this.currentPage)
            },
            okEditor () {
                if (this.createOrEditor) {
                    // 編輯的操作,修改數據
                    this.data1.splice((this.currentPage - 1) * 10 + this.empInfo.index, 1, this.empInfo)
                } else {
                    // 添加的操作,修改數據
                    this.data1.push(Object.assign({}, this.empInfo))
                }
                this.empInfo = {}
            },
            cancelEditor () {
                // 取消編輯的操作
                this.$Message.info({
                    content: '操作取消'
                })
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // 為true時,在首部增加一個索引列
                    this.tableColumns1.unshift({
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // 為false時,若首部存在索引列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // 為 true 時,在首部增加一多選框列,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // 為false時,若存在多選框列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            data1() {
                // 當列表數據改變時(比如刪除某數據),觸發一次刷新列表的操作
                if (!this.createOrEditor) {
                    // 若為添加數據,則跳轉到最后一個頁面
                    this.changePage(Math.ceil(this.data1.length / this.pageSize))
                } else {
                    this.changePage(this.currentPage)
                }
            }
        },
        mounted() {
            // 頁面加載時,觸發第一次刷新列表的操作
            this.changePage(this.currentPage)
        }
    })
</script>
</body>
</html>

 

 

 

 

 

 

2、template/render 模式下

(1)使用 vue-cli3.0 創建項目。

  參考地址:https://www.cnblogs.com/l-y-h/p/11241503.html

 

(2)使用 npm 安裝使用。

  參考地址:https://www.cnblogs.com/l-y-h/p/12001549.html#_label0_1

【main.js】

import Vue from 'vue'
import App from './App.vue'
// step1: 引入 ViewUI
import ViewUI from 'view-design'
// step2: 引入 css 
import 'view-design/dist/styles/iview.css'

Vue.config.productionTip = false
// step3:聲明使用 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>員工列表</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><Button type="primary" icon="md-add" @click="create">添加</Button></i-col>
                    <i-col style="margin-right: 5px"><Button type="success" icon="md-settings" @click="setUp = true">設置</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">編輯</Button>
                        <Button type="error" size="small" @click="remove(index)" icon="ios-trash">刪除</Button>
                    </template>
                </Table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current 設置當前選中頁,pageSize 設置每頁顯示數據的條數-->
                        <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 {
                // 添加與編輯復用 modal 框,false為添加,true為編輯
                createOrEditor: false,
                // 是否打開員工信息框
                empModal: false,
                // 用於保存一個員工的信息
                empInfo: {},
                // 是否打開設置
                setUp: false,
                // 當前頁碼
                currentPage: 1,
                // 每頁數據的條數
                pageSize: 10,
                // 表格的列
                tableColumns1: [{
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        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: '開發部'
                },{
                    deptId: '2',
                    deptName: '測試部'
                },{
                    deptId: '3',
                    deptName: '產品部'
                }],
                // 表格的源數據
                data1: [{
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: '產品部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    }, {
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: '產品部'
                    }
                ],
                // 表格每頁的數據
                data2: [],
                // 表格邊框是否顯示
                showBorder: false,
                // 表格斑馬紋是否顯示
                showStripe: false,
                // 表格頭是否顯示
                showHeader: true,
                // 表格索引是否顯示
                showIndex: true,
                // 表格多選框是否顯示
                showCheckbox: false,
                // 表格滾動條是否開啟
                fixedHeader: false,
                // 改變表格大小
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // 改變當前的頁碼,並獲取當前頁碼所擁有的數據
                this.currentPage = index
                // 注意,此處不能直接用 = 賦值。使用 = 后(指向的地址相同),修改 data2 的同時會修改 data1
                this.data2 = [].concat(this.data1.slice((index - 1) * this.pageSize, index * this.pageSize))
            },
            show(index) {
                // 彈出一個模態框,用於展示某條數據的信息
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {index: index})
            },
            create() {
                // 用於添加一條信息
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(index) {
                // 刪除某條數據(刪除源數據)
                this.data1.splice((this.currentPage - 1) * 10 + index, 1)
            },
            changePageSize(index) {
                // 改變每頁顯示的條數
                this.$Message.info({
                    content: '當前頁面顯示條數修改為: ' + index + '條/頁'
                })
                // 改變后,跳轉到首頁,並刷新列表
                this.currentPage = 1
                this.pageSize = index
                this.changePage(this.currentPage)
            },
            okEditor () {
                if (this.createOrEditor) {
                    // 編輯的操作,修改數據
                    this.data1.splice((this.currentPage - 1) * 10 + this.empInfo.index, 1, this.empInfo)
                } else {
                    // 添加的操作,修改數據
                    this.data1.push(Object.assign({}, this.empInfo))
                }
                this.empInfo = {}
            },
            cancelEditor () {
                // 取消編輯的操作
                this.$Message.info({
                    content: '操作取消'
                })
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // 為true時,在首部增加一個索引列
                    this.tableColumns1.unshift({
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // 為false時,若首部存在索引列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // 為 true 時,在首部增加一多選框列,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // 為false時,若存在多選框列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            data1() {
                // 當列表數據改變時(比如刪除某數據),觸發一次刷新列表的操作
                if (!this.createOrEditor) {
                    // 若為添加數據,則跳轉到最后一個頁面
                    this.changePage(Math.ceil(this.data1.length / this.pageSize))
                } else {
                    this.changePage(this.currentPage)
                }
            }
        },
        mounted() {
            // 頁面加載時,觸發第一次刷新列表的操作
            this.changePage(this.currentPage)
        }
    }
</script>

 

 

 

 

 

 

 

文件目錄結構:

 

 

 

 

 

 八、前端代碼

1、解決跨域問題

  可以參考:https://www.cnblogs.com/l-y-h/p/11815452.html

(1)在 main.js 中配置 baseURL

【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)在 vue.config.js 中配置跨域代理

【vue.config.js】

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                // 此處的寫法,目的是為了 將 /api 替換成 http://localhost:9000/crud
                target: 'http://localhost:9000/crud/',
                // 允許跨域
                changeOrigin: true,
                ws: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
}

 

(3)使用 axios

 

 

 

【自定義一個 api.js 文件】

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)
        })
    })
}


【使用時,在需要使用的地方引入這個js文件即可】
<template>
</template>
<script>
    import { getAllEmps } from './api/api.js'
    export default {
        data() {
            return {
                currentPage: 1,
                pageSize: 2
            }
        },
        mounted() {
            // 不需要使用 this.getAllEmps(),直接使用 getAllEmps() 即可
            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>員工列表</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><Button type="primary" icon="md-add" @click="create">添加</Button></i-col>
                    <i-col style="margin-right: 5px"><Button type="success" icon="md-settings" @click="setUp = true">設置</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">編輯</Button>
                        <Button type="error" size="small" @click="remove(index)" icon="ios-trash">刪除</Button>
                    </template>
                </Table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current 設置當前選中頁,pageSize 設置每頁顯示數據的條數-->
                        <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 {
                // 添加與編輯復用 modal 框,false為添加,true為編輯
                createOrEditor: false,
                // 是否打開員工信息框
                empModal: false,
                // 用於保存一個員工的信息
                empInfo: {},
                // 是否打開設置
                setUp: false,
                // 當前頁碼
                currentPage: 1,
                // 每頁數據的條數
                pageSize: 10,
                // 表格的列
                tableColumns1: [{
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        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: '開發部'
                },{
                    deptId: '2',
                    deptName: '測試部'
                },{
                    deptId: '3',
                    deptName: '產品部'
                }],
                // 表格的源數據
                data1: [{
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: '產品部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    }, {
                        name: 'John Brown',
                        salary: 6000,
                        age: 18,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jim Green',
                        salary: 6000,
                        age: 24,
                        email: '323@163.com',
                        deptId: '1',
                        deptName: '開發部'
                    },
                    {
                        name: 'Joe Black',
                        salary: 6000,
                        age: 30,
                        email: '323@163.com',
                        deptId: '2',
                        deptName: '測試部'
                    },
                    {
                        name: 'Jon Snow',
                        salary: 6000,
                        age: 26,
                        email: '323@163.com',
                        deptId: '3',
                        deptName: '產品部'
                    }
                ],
                // 表格每頁的數據
                data2: [],
                // 表格邊框是否顯示
                showBorder: false,
                // 表格斑馬紋是否顯示
                showStripe: false,
                // 表格頭是否顯示
                showHeader: true,
                // 表格索引是否顯示
                showIndex: true,
                // 表格多選框是否顯示
                showCheckbox: false,
                // 表格滾動條是否開啟
                fixedHeader: false,
                // 改變表格大小
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // 改變當前的頁碼,並獲取當前頁碼所擁有的數據
                this.currentPage = index
                // 注意,此處不能直接用 = 賦值。使用 = 后(指向的地址相同),修改 data2 的同時會修改 data1
                this.data2 = [].concat(this.data1.slice((index - 1) * this.pageSize, index * this.pageSize))
            },
            show(index) {
                // 彈出一個模態框,用於展示某條數據的信息
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {index: index})
            },
            create() {
                // 用於添加一條信息
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(index) {
                // 刪除某條數據(刪除源數據)
                this.data1.splice((this.currentPage - 1) * 10 + index, 1)
            },
            changePageSize(index) {
                // 改變每頁顯示的條數
                this.$Message.info({
                    content: '當前頁面顯示條數修改為: ' + index + '條/頁'
                })
                // 改變后,跳轉到首頁,並刷新列表
                this.currentPage = 1
                this.pageSize = index
                this.changePage(this.currentPage)
            },
            okEditor () {
                if (this.createOrEditor) {
                    // 編輯的操作,修改數據
                    this.data1.splice((this.currentPage - 1) * 10 + this.empInfo.index, 1, this.empInfo)
                } else {
                    // 添加的操作,修改數據
                    this.data1.push(Object.assign({}, this.empInfo))
                }
                this.empInfo = {}
            },
            cancelEditor () {
                // 取消編輯的操作
                this.$Message.info({
                    content: '操作取消'
                })
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // 為true時,在首部增加一個索引列
                    this.tableColumns1.unshift({
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // 為false時,若首部存在索引列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // 為 true 時,在首部增加一多選框列,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // 為false時,若存在多選框列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            data1() {
                // 當列表數據改變時(比如刪除某數據),觸發一次刷新列表的操作
                if (!this.createOrEditor) {
                    // 若為添加數據,則跳轉到最后一個頁面
                    this.changePage(Math.ceil(this.data1.length / this.pageSize))
                } else {
                    this.changePage(this.currentPage)
                }
            }
        },
        mounted() {
            // 頁面加載時,觸發第一次刷新列表的操作
            this.changePage(this.currentPage)
            // 不需要使用 this.getAllEmps(),直接使用 getAllEmps() 即可
            getAllEmps({
                pageNum: this.currentPage,
                pageSize: this.pageSize
            }).then((res) => {
          console.log(res)
        }) } }
</script>

 

2、調用接口、與后台進行交互

(1)接口詳情

【獲取所有emp信息(分頁查詢)】
GET                                            param
http://localhost:9000/crud/emps/{pageNum}      pageSize

【獲取某個員工的信息(沒用上)】
GET
http://localhost:9000/crud/emp/{id}

【刪除某個員工的信息】
DELETE
http://localhost:9000/crud/emp/{id}

【插入某條數據】
POST
http://localhost:9000/crud/emp                Employee

【更新某條數據】
PUT
http://localhost:9000/crud/emp/{id}           Employee

【獲取部門信息】
GET
http://localhost:9000/crud/depts

 

(2)完整代碼

  代碼結構截圖:

 

 

 

【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>員工列表</h1>
                    </Divider>
                </row>
                <row justify="end" type="flex">
                    <i-col style="margin-right: 5px"><Button type="primary" icon="md-add" @click="create">添加</Button></i-col>
                    <i-col style="margin-right: 5px"><Button type="success" icon="md-settings" @click="setUp = true">設置</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">編輯</Button>
                        <Button type="error" size="small" @click="remove(row, index)" icon="ios-trash">刪除</Button>
                    </template>
                </Table>
                <div style="margin: 10px;overflow: hidden">
                    <div style="float: right;">
                        <!-- current 設置當前選中頁,pageSize 設置每頁顯示數據的條數-->
                        <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 {
                // 保存列表的總數據
                total: 0,
                // 添加與編輯復用 modal 框,false為添加,true為編輯
                createOrEditor: false,
                // 是否打開員工信息框
                empModal: false,
                // 用於保存一個員工的信息
                empInfo: {},
                // 是否打開設置
                setUp: false,
                // 當前頁碼
                currentPage: 1,
                // 每頁數據的條數
                pageSize: 10,
                // 表格的列
                tableColumns1: [{
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        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: [],
                // 表格每頁的數據
                data2: [],
                // 表格邊框是否顯示
                showBorder: false,
                // 表格斑馬紋是否顯示
                showStripe: false,
                // 表格頭是否顯示
                showHeader: true,
                // 表格索引是否顯示
                showIndex: true,
                // 表格多選框是否顯示
                showCheckbox: false,
                // 表格滾動條是否開啟
                fixedHeader: false,
                // 改變表格大小
                tableSize: 'default'
            }
        },
        methods: {
            changePage(index) {
                // 改變當前的頁碼,並獲取當前頁碼所擁有的數據
                this.currentPage = index

                // 獲取emps數據,分頁查詢
                getAllEmps({
                    pageNum: this.currentPage,
                    pageSize: this.pageSize
                }).then((res) => {
                    if (res.data.success) {
                        // 保存獲取到的 emp 列表
                        this.data2 = res.data.pageInfo.list
                        // 保存獲取數據的總數
                        this.total = res.data.pageInfo.total
                    }
                    this.noticeType(res.data.level, res.data.messages)
                }).catch((res) => {
                    this.noticeType()
                })
            },
            show(index) {
                // 彈出一個模態框,用於展示某條數據的信息
                this.empInfo = Object.assign(this.empInfo, this.data2[index])
                this.empModal = true
                this.createOrEditor = true
                this.empInfo = Object.assign(this.empInfo, {
                    index: index
                })
            },
            create() {
                // 用於添加一條信息
                this.empInfo = []
                this.empModal = true
                this.createOrEditor = false
            },
            remove(row, index) {
                this.$Modal.confirm({
                    title: '刪除',
                    content: '<p>是否刪除當前數據</p>',
                    onOk: () => {
                        // 刪除某個員工的數據
                        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('取消刪除')
                    },
                    okText: 'OK',
                    cancelText: 'Cancel'
                })
            },
            changePageSize(index) {
                // 改變每頁顯示的條數
                this.$Message.info({
                    content: '當前頁面顯示條數修改為: ' + index + '條/頁'
                })
                // 改變后,跳轉到首頁,並刷新列表
                this.pageSize = index
                if(this.currentPage === 1) {
                    this.changePage(this.currentPage)
                    return
                }
                this.currentPage = 1
            },
            okEditor() {
                if (this.createOrEditor) {
                    // 更新某個員工的數據
                    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 {
                    // 新增某個員工
                    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() {
                // 取消編輯的操作
                this.$Message.info({
                    content: '操作取消'
                })
            },
            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: '系統異常',
                            duration: 2
                        })
                        break
                }
            }
        },
        watch: {
            showIndex(newVal) {
                if (newVal) {
                    // 為true時,在首部增加一個索引列
                    this.tableColumns1.unshift({
                        // 分頁時,若要出現自動索引,設置type = "index2",並使用 render 來返回索引值
                        type: 'index2',
                        width: 80,
                        align: 'center',
                        render: (h, params) => {
                            return h('span', params.index + (this.currentPage - 1) * this.pageSize + 1);
                        }
                    })
                } else {
                    // 為false時,若首部存在索引列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'index2') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            showCheckbox(newVal) {
                if (newVal) {
                    // 為 true 時,在首部增加一多選框列,
                    this.tableColumns1.unshift({
                        type: 'selection',
                        width: 60,
                        align: 'center'
                    })
                } else {
                    // 為false時,若存在多選框列,則移除該列
                    this.tableColumns1.forEach((item, index) => {
                        if (item.type === 'selection') {
                            this.tableColumns1.splice(index, 1)
                        }
                    })
                }
            },
            empModal(newVal) {
                // 如果打開模態框,則觸發一次獲取部門信息的操作
                if (newVal) {
                    // 獲取部門信息
                    getDeptName().then((res) => {
                        if (res.data.success) {
                            // 使用 Object.assign 給對象賦值時,推薦使用如下方法,創建一個新的對象。
                            // 若仍使用同一對象,比如this.dept = Object.assign(this.dept, res.data.departments),vue可能監控不到它的變化。
                            this.dept = Object.assign({}, this.dept, res.data.departments)
                        }
                    }).catch((res) => {
                        this.noticeType()
                    })
                }
            }
        },
        mounted() {
            // 頁面加載時,觸發第一次刷新列表的操作
            this.changePage(this.currentPage)
        }
    }
</script>



【api.js】
import Axios from 'axios'

/**
 * 獲取emps數據,分頁查詢
 * @param {Object} params 分頁參數(pageNum當前頁碼, pageSize每頁數據總數) 
 */
export function getAllEmps(params) {
    return new Promise((resolve, reject) => {
        Axios.get('/emps/' + params.pageNum, {
            params
        }).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * 獲取某個員工的數據
 * @param {Object} params 參數為員工的 id
 */
export function getEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.get('/emp/' + params.id).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * 刪除某個員工的數據
 * @param {Object} params 參數為員工的 id
 */
export function deleteEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.delete('/emp/' + params.id).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * 更新某個員工的數據
 * @param {Object} params 參數為員工的 id,以及員工數據
 */
export function updateEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.put('/emp/' + params.id, params).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * 新增某個員工
 * @param {Object} params 參數為員工的 id,以及員工數據
 */
export function insertEmp(params) {
    return new Promise((resolve, reject) => {
        Axios.post('/emp', params).then(res => {
            resolve(res)
        }).catch(res => {
            reject(res)
        })
    })
}

/**
 * 獲取部門信息
 * @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': {
                // 此處的寫法,目的是為了 將 /api 替換成 http://localhost:9000/crud
                target: 'http://localhost:9000/crud/',
                // 允許跨域
                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"
  ]
}

 

 

九、前后端項目啟動

1、前端項目啟動

(1)項目地址:
  https://github.com/lyh-man/ssm_crud-front.git
(2)前提:
  安裝 node.js(為了使用 npm)。
(3)啟動:

將項目copy下來,並通過命令行進入該目錄。

【Project setup】
Step1:  npm install

【Compiles and hot-reloads for development】
Step2:  npm run serve

【Compiles and minifies for production】
可選:   npm run build

【Run your tests】
可選:   npm run test

【Lints and fixes files】
可選:   npm run lint

 

 

2、后端項目啟動

(1)項目地址:https://github.com/lyh-man/ssm_crud-back.git
(2)使用 IDEA 打開項目,等待 maven 下載相關依賴。
(3)Step1:打開 Edit Configurations...

 

 

(4)Step2:點擊 + 號,並找到 maven

 

 (5)配置項目地址、以及端口號

 

 (6)運行即可

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM