欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

程序员文章站 2022-05-25 19:47:38
JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人【梦在旅途原创】,文中内容可能部份图片、代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署 第三篇:JAVA WEB快 ......

java web快速入门系列之前的相关文章如下:(文章全部本人【梦在旅途原创】,文中内容可能部份图片、代码参照网上资源)

第一篇:java web快速入门之环境搭建

第二篇:java web快速入门之从编写一个jsp web网站了解jsp web网站的基本结构、调试、部署

第三篇:java web快速入门之通过一个简单的spring项目了解spring的核心(aop、ioc)

第四篇:java web快速入门之从编写一个基于springmvc框架的网站了解maven、springmvc、springjdbc

 

今天是第五篇,也是该系列文章的最后一篇,接上篇《java web快速入门之从编写一个基于springmvc框架的网站了解maven、springmvc、springjdbc》,通过上篇文章的详细介绍,知道如何使用maven来快速构建spring mvc应用,也能够使用spring mvc+springjdbc实现网站开发,而本文所涉及的知识则是在这基础之上继续提升,核心是讲解如何使用spring boot来更快速的构建spring mvc,并通过mybatis及代码生成相关dao,同时利用vue前端框架开发前后端分离的网站,用户体验更好,废话不多说,直接进入本文主题。

(提示:本文内容有点长,涉及的知识点也比较多,若是新手建议耐心看完!)

一、创建spring boot+springmvc空项目

  1.1通过https://start.spring.io/官网快速生成一个spring boot+springmvc空项目,如下图示:

(当然也可以通过eclipse或idea的spring boot插件来创建,可参见:,)

  JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

  设置后点击页面的生成项目按钮,即可生成并下载spring boot项目代码压缩包,然后使用ide导入存在的maven project即可。

  1.2调整项目,解决一些踩坑点

  1.2.1.调整spring boot app启动类(如:springbootdemoapplication)到根包目录或在启动类上显式添加@componentscan注解,并指定包路径,如下代码所示,cn.zuowenjun.boot是根包目录,其余都是cn.zuowenjun.boot的子包

package cn.zuowenjun.boot;

import org.mybatis.spring.annotation.mapperscan;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.transaction.annotation.enabletransactionmanagement;
//import org.springframework.context.annotation.componentscan;

@springbootapplication //指定为spring boot启动入口,内含多个spring所需要的注解
@mapperscan(basepackages="cn.zuowenjun.boot.mapper")//设置mybaits扫描的mapper包路径
//@componentscan(basepackages= {"cn.zuowenjun.controller"}) //如果不在根包目录,则需指定spring管理的相关包路径
@enabletransactionmanagement //启动事务管理
public class springbootdemoapplication {

    public static void main(string[] args) {
        springapplication.run(springbootdemoapplication.class, args);
    }

}

  1.2.2.解决pom文件报:

description resource path location type
execution default-resources of goal org.apache.maven.plugins:maven-resources-plugin:3.1.0:resources failed: unable to load the mojo 'resources' (or one of its required components) from the plugin 'org.apache.maven.plugins:maven-resources-plugin:3.1.0'

直接在pom中添加如下resources依赖:

        <dependency>
            <groupid>org.apache.maven.plugins</groupid>
            <artifactid>maven-resources-plugin</artifactid>
            <version>2.5</version>
            <type>maven-plugin</type>
        </dependency>

  1.2.3.设置热编译启动模式,以便可以随时更改代码后即时生效

<dependencies>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-devtools</artifactid>
        <optional>true</optional>
   </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-maven-plugin</artifactid>
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>
   </plugins>
</build>

设置后项目的视图就有如下显示效果:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

  1.3演示请求rest api分别返回json、xml

   创建好spring boot空项目环境后,我们就可以开始编写相关代码了,在此仅贴出实现了rest api分别响应返回json、xml格式的controller,实现步骤如下:

   1.3.1在cn.zuowenjun.boot.controller包中创建democontroller,并编写hellojson、helloxml action方法,代码如下:

package cn.zuowenjun.boot.controller;

import org.springframework.web.bind.annotation.*;

import cn.zuowenjun.boot.domain.*;

@restcontroller
public class democontroller {

    @requestmapping(value="/hello/json",produces="application/json;charset=utf-8")
    public hellodto hellojson()
    {
        hellodto dto=new hellodto();
        dto.setmessage("hello,zuowenjun.cn,hello java spring boot!");
        
        return dto;
    }
    
    @requestmapping(value="/hello/xml",produces="text/xml;charset=utf-8")
    public hellodto helloxml()
    {
        hellodto dto=new hellodto();
        dto.setmessage("hello,zuowenjun.cn,hello java spring boot!");
        
        return dto;
    }
}

如上代码简要说明:@restcontroller相当于是:@controller、@responsebody,这个可以查看@restcontroller注解类代码就知道;@requestmapping指定请求映射,其中produces设置响应内容格式(可理解为服务端是生产者,而用户在浏览器端【客户端】是消费端),还有consumes属性,这个是指可接收请求的内容格式(可理解为用户在浏览器端发送请求是消息的生产者,而服务端接收并处理该请求为消息的消费者),当然还有其它一些属性,大家可以参见我上篇文章或网络其它大神的相关文章加以了解。

另外需要注意,默认spring mvc只返回json格式,若需返回xml格式,还需添加xml jar包依赖,如下:(可以看到version这里我指定了版本号区间,表示2.5.0及以上版本都可以,有些依赖spring-boot-starter-parent中都有提前配置依赖管理,我们只需要指定groupid、artifactid即可,version就会使用spring boot中的默认版本,当然也可以强制指定版本)

        <!-- 如果项目中需要rest api响应(返回)xml格式的报文体则应添加该依赖 -->
        <dependency>
            <groupid>com.fasterxml.jackson.jaxrs</groupid>
            <artifactid>jackson-jaxrs-xml-provider</artifactid>
            <version>[2.5.0,)</version><!--$no-mvn-man-ver$ -->
        </dependency>

由于项目中同时添加json及xml的jar包,按照spring mvc的默认响应处理流程是:如果未指定produces,则当请求的header中指定了accept类型,则自动格式化并返回该accept所需的类型,如果未指定accept类型,则优先是响应xml,当找不到xml依赖包时才会响应json,故如果项目中同时有json及xml,那么最好显式指定produces或者请求头上指明accept类型 这一点与asp.net web api原理相同,因为都是符合rest架构风格的。

效果如下:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识     JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

二、使用mybatis框架完成domain层、dao层(这里是mapper层) ---提示:由于篇幅有限,只贴出重点能体现不同知识点的代码,其余可以到github上查看下载源码进行详细了解

  2.0:首先在application.properties配置mybatis的相关选项,如下所示:

mybatis.type-aliases-package=cn.zuowenjun.boot.domain #包类型别名,这样在xml中就可以简写成类名
mybatis.config-location=classpath:mybatis/mybatis-config.xml #指定mybatis的配置文件路径
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml #指定mapper xml的存放路径

#这里是使用sql server,如果是其它db则使用其它驱动
spring.datasource.driverclassname=com.microsoft.sqlserver.jdbc.sqlserverdriver
spring.datasource.url=jdbc:sqlserver://dbip:port;databasename=testdb
spring.datasource.username=dbuser
spring.datasource.password=dbpassword

   其次添加mybatis-spring-boot-starter maven依赖,它会自动添加相关的mybatis依赖包,配置如下:

        <!-- 添加 mybatis-spring-boot依赖,直接可以使用mybatis环境操作db-->
        <dependency>
            <groupid>org.mybatis.spring.boot</groupid>
            <artifactid>mybatis-spring-boot-starter</artifactid>
            <version>1.3.2</version>
        </dependency>

  2.1全手写java代码实现mybatis的crud;

  2.1.1.在cn.zuowenjun.boot.domain包【实体模型或称领域模型层,这里算不上真正的领域模型,最多算是贫血的领域模型】中定义数据实体模型(goods:商品信息),代码如下:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
package cn.zuowenjun.boot.domain;

import java.math.bigdecimal;
import java.util.date;

public class goods {
    private int id;
    private string title;
    private string picture;
    private bigdecimal price;
    private string introduction;
    private int categoryid;
    private string lasteditby;
    private date lastedittime;
    
    public goods() {
        
    }
    
    public goods(int id,string title,string picture,
            bigdecimal price,string introduction,int categoryid,string lasteditby,date lastedittime) {
        this.setid(id);
        this.settitle(title);
        this.setpicture(picture);
        this.setprice(price);
        this.setintroduction(introduction);
        this.setcategoryid(categoryid);
        this.setlasteditby(lasteditby);
        this.setlastedittime(lastedittime);
    }
    
    public int getid() {
        return id;
    }
    public void setid(int id) {
        this.id = id;
    }
    
    public string gettitle() {
        return title;
    }
    public void settitle(string title) {
        this.title = title;
    }
    
    public string getpicture() {
        return picture;
    }
    public void setpicture(string picture) {
        this.picture = picture;
    }
    
    public bigdecimal getprice() {
        return price;
    }
    
    public void setprice(bigdecimal price) {
        this.price = price;
    }
    
    public string getintroduction() {
        return introduction;
    }
    public void setintroduction(string introduction) {
        this.introduction = introduction;
    }
    
    public int getcategoryid() {
        return categoryid;
    }
    public void setcategoryid(int categoryid) {
        this.categoryid = categoryid;
    }
    
    public string getlasteditby() {
        return lasteditby;
    }
    public void setlasteditby(string lasteditby) {
        this.lasteditby = lasteditby;
    }
    
    public date getlastedittime() {
        return lastedittime;
    }
    public void setlastedittime(date lastedittime) {
        this.lastedittime = lastedittime;
    }

}
view code

  2.1.2.在cn.zuowenjun.boot.mapper包【数据映射处理层或称dao层】中定义数据映射处理接口及添加相应的sql注解,以实现对数据进行crud,代码如下:

package cn.zuowenjun.boot.mapper;

import java.util.*;

import org.apache.ibatis.annotations.*;

import cn.zuowenjun.boot.domain.*;

public interface goodsmapper {
    
    @select("select * from ta_testgoods order by id offset (${pageno}-1)*${pagesize} rows fetch next ${pagesize} rows only")
    list<goods> getlistbypage(int pagesize,int pageno);
    
    @select("select * from ta_testgoods where categoryid=#{categoryid} order by id")
    list<goods> getlist(int categoryid);
    
    @select("<script>select * from ta_testgoods where id in " 
            +"<foreach item='item' index='index' collection='ids' open='(' separator=',' close=')'>#{item}</foreach>"
            +"order by id</script>")
    list<goods> getlistbymultids(@param("ids")int...ids);
    
    @select("select * from ta_testgoods where id=#{id}")
    goods get(int id);
    

    @insert(value="insert into ta_testgoods(title, picture, price, introduction, categoryid, "
            + "lasteditby, lastedittime) values(#{title},#{picture},#{price},#{introduction},#{categoryid},#{lasteditby},getdate())")
    @options(usegeneratedkeys=true,keyproperty="id",keycolumn="id")
    void insert(goods goods);
    
    @delete(value="delete from ta_testgoods where id=#{id}")
    void delete(int id);
    
    @update("update ta_testgoods set title=#{title},picture=#{picture},price=#{price},introduction=#{introduction}," + 
            "categoryid=#{categoryid},lasteditby=#{lasteditby},lastedittime=getdate()  " + 
            "where id=#{id}")
    void update(goods goods);
    
    
}

 如上代码重点说明:

a.增删改查,对应的注解是:insert、delete、update、select;

b.sql注解中的参数占位符有两种,一种是:#{xxx},最后会生成?的参数化执行,另一种是:${xxx} 则最后会直接替换成参数的值,即拼sql(除非信任参数或一些时间、数字类型,否则不建议这种,存在sql注入风险);

c.insert时如果有自增id,则可以通过添加options注解,并指定usegeneratedkeys=true,keyproperty="数据实体类的属性字段名",keycolumn="表自增id的字段名",这样当insert成功后会自动回填到数据实体类的自增id对应的属性上;

d.如果想要生成in子句查询,则如上代码getlistbymultids方法上的select注解中使用<script>xxx<foreach>xx</foreach>xx</script>格式实现,如果想用实现复杂的一对一,一对多,多对多等复杂的查询,则需要添加results注解并指定相应的关联关系,同时select sql语句也应关联查询,可参见:

以上2步即完成一个mapper操作类;

  2.2全手写ava代码+mapper xml实现mybatis的crud;

  2.2.1.仍然是在cn.zuowenjun.boot.domain包中定义一个数据实体模型类(shoppingcart:购物车信息),代码如下:【注意这里有一个关联商品信息的属性:ingoods】

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
package cn.zuowenjun.boot.domain;

import java.util.date;

public class shoppingcart {
    private int id;
    private string shopper;
    private int goodsid;
    private int qty;
    private date addedtime;
    private goods ingoods;
    
    public shoppingcart() {
        
    }
    
    public shoppingcart(int id,string shopper,int goodsid,int qty,date addedtime) {
        this.id=id;
        this.shopper=shopper;
        this.goodsid=goodsid;
        this.qty=qty;
        this.addedtime=addedtime;
    }
    
    
    public int getid() {
        return id;
    }
    public void setid(int id) {
        this.id = id;
    }
    
    public string getshopper() {
        return shopper;
    }
    public void setshopper(string shopper) {
        this.shopper = shopper;
    }
    
    public int getgoodsid() {
        return goodsid;
    }
    public void setgoodsid(int goodsid) {
        this.goodsid = goodsid;
    }
    
    public int getqty() {
        return qty;
    }
    public void setqty(int qty) {
        this.qty = qty;
    }
    
    public date getaddedtime() {
        return addedtime;
    }
    public void setaddedtime(date addedtime) {
        this.addedtime = addedtime;
    }

    public goods getingoods() {
        return ingoods;
    }

    public void setingoods(goods ingoods) {
        this.ingoods = ingoods;
    }

    

}
view code

  2.2.2.仍然是在cn.zuowenjun.boot.mapper包中定义数据操作接口(interface),注意这里只是定义接口,并不包含sql注解部份,因为这部份将在mapper的xml代码中进行配置实现,代码如下:

package cn.zuowenjun.boot.mapper;

import java.util.list;

import org.apache.ibatis.annotations.param;

import cn.zuowenjun.boot.domain.*;

public interface shoppingcartmapper {
    
    list<shoppingcart> getlist(string shopper);
    
    void insert(shoppingcart shoppingcart);
    
    void update(shoppingcart shoppingcart);
    
    void deleteitem(int id);
    
    void delete(string shopper);
    
    int getbuycount(string shopper);
    
    shoppingcart get(@param("shopper") string shopper,@param("goodsid") int goodsid); 
}

如上代码有一个重点说明:get方法有两个参数(多个参数也类似),为了mybatis能够自动映射到这些参数,必需为每个参数添加param注解,并指定参数名,这个参数名是与对应的mapper xml中的sql语句中定义的参数名相同。

  2.2.3.在mybatis.mapper-locations设置的mapper xml存放的路径中创建xml文件,并手动编写映射的sql语句,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.zuowenjun.boot.mapper.shoppingcartmapper">
    <resultmap id="shoppingcartmap" type="shoppingcart" >
        <id column="id" property="id" jdbctype="integer" />
        <result column="shopper" property="shopper" jdbctype="nvarchar" />
        <result column="goodsid" property="goodsid" jdbctype="integer" />
        <result column="qty" property="qty" jdbctype="integer"/>
        <result column="addedtime" property="addedtime" jdbctype="date" />
        <!-- referseee https://www.cnblogs.com/ysocean/p/7237499.html -->
        <association property="ingoods" javatype="cn.zuowenjun.boot.domain.goods">
            <id column="id" property="id" jdbctype="integer" />
            <result column="title" property="title" />
            <result column="picture" property="picture" />
            <result column="price" property="price" />
            <result column="introduction" property="introduction" />
            <result column="categoryid" property="categoryid" />
            <result column="lasteditby" property="lasteditby" />
            <result column="lastedittime" property="lastedittime" />
        </association>
    </resultmap>

    <!-- 如果返回的结果与某个实体类完全相同,其实完全不需要上面的resultmap,而是直接使用resulttype=类名,
        如:resulttype=cn.zuowenjun.boot.domain.shoppingcart(简写别名:shoppingcart),此处是示例用法,故采取指定映射 -->
    <select id="getlist" parametertype="string" resultmap="shoppingcartmap">
        select * from ta_testshoppingcart a inner join ta_testgoods b  on a.goodsid=b.id  
        where shopper=#{shopper} order by addedtime
    </select>
    
    <select id="getbuycount" parametertype="string" resulttype="int">
        select count(1) from (select goodsid from ta_testshoppingcart where shopper=#{shopper} 
        group by goodsid) as t
    </select>
    
    <select id="get"  resultmap="shoppingcartmap">
         select * from ta_testshoppingcart a inner join ta_testgoods b  on a.goodsid=b.id  
         where shopper=#{shopper} and goodsid=#{goodsid}
    </select>
    
    <insert id="insert" parametertype="shoppingcart" 
        usegeneratedkeys="true" keyproperty="id" keycolumn="id">
        insert into ta_testshoppingcart(shopper, goodsid, qty, addedtime) 
        values(#{shopper},#{goodsid},#{qty},getdate())
    </insert>
    
    <update id="update" parametertype="shoppingcart" >
        update ta_testshoppingcart set shopper=#{shopper},goodsid=#{goodsid},qty=#{qty},addedtime=getdate() 
        where id=#{id}
    </update>
    
    <delete id="deleteitem" parametertype="int">
        delete from ta_testshoppingcart where id=#{id}
    </delete>
    
    <delete id="delete" parametertype="string">
        delete from ta_testshoppingcart where shopper=#{shopper}
    </delete>
    
    
</mapper>

如上xml重点说明:

a.凡是使用到类型的地方,可以在mybatis-config.xml中提前配置类型别名,以简化配置,当然mybatis已默认设置了一些别名以减少大家配置的工作量,如:string,对应的类型是string等,详见:http://www.mybatis.org/mybatis-3/zh/configuration.html#typealiases

b.由于这个shoppingcart有关联属性:ingoods,故在查询时都会关联查询goods表并通过在resultmap中通过association 元素来指定关联关系,更多复杂的xml配置详见:

以上3步即完成一个mapper操作类,相比直接使用mapper接口+sql注解多了一个步骤,但这样的好处是由于没有写死在代码中,可以很容易的更改mapper的相关sql语句,减少代码改动量。

  2.3使用mybatis generator的maven插件自动生成mybatis的crud;

   通过上面的介绍,我们知道有2种方法来实现一个mapper数据操作类(dao),显然第2种更能适应更改的情况,但由于手写mapper xml文件非常的麻烦,故可以通过mybatis generator组件,自动生成相关的代码及xml(一般是:数据实体类domain、数据处理接口mapper、mapper xml),具体实现步骤如下:(可以单独一个项目来生成这些文件,也可以集成在一个项目中,由于是演示,我这里是集成在一个项目中)

  2.3.1.由于要使用mybatis generator组件,故需要添加对应的jar包依赖,如下所示:

        <!--sql server 数据驱动,以提供数据访问支持-->
<dependency>
            <groupid>com.microsoft.sqlserver</groupid>
            <artifactid>mssql-jdbc</artifactid>
            <version>7.0.0.jre8</version><!--$no-mvn-man-ver$ -->
        </dependency>


        <!-- 添加mybatis生成器,以便通过maven build自动生成model、mapper及xml -->
        <dependency>
            <groupid>org.mybatis.generator</groupid>
            <artifactid>mybatis-generator-core</artifactid>
            <version>1.3.7</version>
        </dependency>

同时需要添加对应的maven插件,以便通过maven命令可执行生成过程,如下:(通过configurationfile元素指定生成器的配置路径,overwrite元素指定是否覆盖生成,这里有个坑,后面会介绍到,此处略)

<build>
        <plugins>            
      <plugin>
                <!--ref: https://gitee.com/free/mybatis_utils/blob/master/mybatisgeneator/mybatisgeneator.md -->
                <!--ref: https://www.cnblogs.com/handsomeye/p/6268513.html -->
                <groupid>org.mybatis.generator</groupid>
                <artifactid>mybatis-generator-maven-plugin</artifactid>
                <version>1.3.7</version>
                <configuration>
                    <configurationfile>src/main/resources/mybatis/generatorconfig.xml</configurationfile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
  </build>

 2.3.2.在cn.zuowenjun.boot.domain包中定义相关的数据实体模型类,我这里演示的类是:shoppingorder(购物订单信息),代码如下:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
package cn.zuowenjun.boot.domain;

import java.math.bigdecimal;
import java.util.date;

public class shoppingorder {
    private integer id;

    private string shopper;

    private integer totalqty;

    private bigdecimal totalprice;

    private boolean iscompleted;

    private string createby;

    private date createtime;

    public integer getid() {
        return id;
    }

    public void setid(integer id) {
        this.id = id;
    }

    public string getshopper() {
        return shopper;
    }

    public void setshopper(string shopper) {
        this.shopper = shopper == null ? null : shopper.trim();
    }

    public integer gettotalqty() {
        return totalqty;
    }

    public void settotalqty(integer totalqty) {
        this.totalqty = totalqty;
    }

    public bigdecimal gettotalprice() {
        return totalprice;
    }

    public void settotalprice(bigdecimal totalprice) {
        this.totalprice = totalprice;
    }

    public boolean getiscompleted() {
        return iscompleted;
    }

    public void setiscompleted(boolean iscompleted) {
        this.iscompleted = iscompleted;
    }

    public string getcreateby() {
        return createby;
    }

    public void setcreateby(string createby) {
        this.createby = createby == null ? null : createby.trim();
    }

    public date getcreatetime() {
        return createtime;
    }

    public void setcreatetime(date createtime) {
        this.createtime = createtime;
    }
}
view code

  2.3.3.配置generatorconfig.xml,指定生成的各个细节,由于generatorconfig的配置节点比较多,如下只是贴出当前示例的配置信息,有一点要说明,注意配置节点的顺序,如果顺序不对就会报错,完整的配置方法详情介绍可参见:https://gitee.com/free/mybatis_utils/blob/master/mybatisgeneator/mybatisgeneator.md 或 

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
<?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>
    <properties resource="application.properties" />
    <!-- https://blog.csdn.net/zsy3313422/article/details/53190613 -->
    <classpathentry
        location="e:/localmvnrepositories/com/microsoft/sqlserver/mssql-jdbc/7.0.0.jre8/mssql-jdbc-7.0.0.jre8.jar" />
    <context id="my" targetruntime="mybatis3simple" defaultmodeltype="flat">
        <property name="javafileencoding" value="utf-8" />

        
        <commentgenerator>
            <property name="suppressallcomments" value="true" />
            <property name="suppressdate" value="true" />
        </commentgenerator>
        <jdbcconnection
            driverclass="${spring.datasource.driverclassname}"
            connectionurl="${spring.datasource.url}"
            userid="${spring.datasource.username}"
            password="${spring.datasource.password}">
        </jdbcconnection>

        <!-- 生成model实体类文件位置 -->
        <javamodelgenerator
            targetpackage="cn.zuowenjun.boot.domain"
            targetproject="src/main/java">
            <property name="enablesubpackages" value="false" />
            <property name="trimstrings" value="true" />
        </javamodelgenerator>

        <!-- 生成mapper.xml配置文件位置 -->
        <!-- targetpackage这里指定包名,则会在如下的路径中生成多层级目录 -->
        <sqlmapgenerator targetpackage="mybatis.mapper"
            targetproject="src/main/resources">
            <property name="enablesubpackages" value="false" />
        </sqlmapgenerator>

        <!-- 生成mapper接口文件位置 -->
        <javaclientgenerator
            targetpackage="cn.zuowenjun.boot.mapper"
            targetproject="src/main/java" type="xmlmapper">
            <property name="enablesubpackages" value="false" />
        </javaclientgenerator>

        <table tablename="ta_testshoppingorder"
            domainobjectname="shoppingorder">
            <generatedkey column="id" sqlstatement="jdbc"  identity="true" /><!-- 指示id为自增id列,并在插入后返回该id -->
        </table>



    </context>
</generatorconfiguration> 
view code

由于涉及的知识点比较多,在此就不作介绍,请参见我给出的链接加以了解。

  2.3.4.通过maven 插件来执行生成代码(生成代码有很多种方法,详见:),这里我使用最为方便的一种,步骤如下:

  项目右键-》runas或者debug-》maven build...-》在goals(阶段)中输入:mybatis-generator:generate,即:设置生成阶段,最后点击apply或直接run即可,如图示:

  JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

  执行生成后,会在控制台中显示最终的结果,如下图示:如果成功会显示buid success,并会在相应的目录中生成对应的文件

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

  2.4进阶用法:自定义mybatis generator的生成过程中的插件类,以便添加额外自定义的方法

  虽然使用mybatis generator减少了手工编写代码及xml的工作量,但由于生成的crud方法都是比较简单的,稍微复杂或灵活一点的方法都不能简单生成,如果单纯的在生成代码后再人工手动添加其它自定义的方法,又担心如果执行一次自动生成又会覆盖手动添加的自定义代码,那有没有办法解决呢?当然是有的,我(梦在旅途,zuowenjun.cn)在网络上了解到的方法大部份都是说获取mybatis generator源代码,然后进行二次开发,最后使用“定制版”的mybatis generator,我个人觉得虽然能解决问题,但如果能力不足,可能会出现意想不到的问题,而且进行定制也不是那么简单的,故我这里采取mybatis generator框架提供的可扩展插件plugin来实现扩展,具体步骤如下:

  2.4.1.在项目新创建一个包cn.zuowenjun.boot.mybatis.plugin,然后在包里面先创建一个泛型通用插件基类(customappendmethodplugin),这个基类主要是用于附加自定义方法,故取名customappendmethodplugin,代码如下:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
package cn.zuowenjun.boot.mybatis.plugin;

import java.util.list;

import org.mybatis.generator.api.introspectedtable;
import org.mybatis.generator.api.pluginadapter;
import org.mybatis.generator.api.dom.java.interface;
import org.mybatis.generator.api.dom.java.toplevelclass;
import org.mybatis.generator.api.dom.xml.document;
import org.mybatis.generator.codegen.mybatis3.javamapper.elements.abstractjavamappermethodgenerator;
import org.mybatis.generator.codegen.mybatis3.xmlmapper.elements.abstractxmlelementgenerator;

/*
 * 自定义通用可添加生成自定义方法插件类
 * author:zuowenjun
 * date:2019-1-29
 */
public abstract class customappendmethodplugin<te extends abstractxmlelementgenerator,tm extends abstractjavamappermethodgenerator>  
extends pluginadapter {

    protected final class<te> teclass;
    protected final class<tm> tmclass;
    
    
    @suppresswarnings("unchecked")
    public customappendmethodplugin(class<? extends abstractxmlelementgenerator> teclass,
            class<? extends abstractjavamappermethodgenerator> tmclass) {
        this.teclass=(class<te>) teclass;
        this.tmclass=(class<tm>) tmclass;
    }
    
    @override
    public boolean sqlmapdocumentgenerated(document document,
            introspectedtable introspectedtable) {
            
            try {
                abstractxmlelementgenerator elementgenerator = teclass.newinstance();
                elementgenerator.setcontext(context);
                elementgenerator.setintrospectedtable(introspectedtable);
                elementgenerator.addelements(document.getrootelement());
                
            } catch (instantiationexception | illegalaccessexception e) {
                // todo auto-generated catch block
                e.printstacktrace();
            }
            

        return super.sqlmapdocumentgenerated(document, introspectedtable);
    }
    
    @override
    public boolean clientgenerated(interface interfaze,
            toplevelclass toplevelclass,
            introspectedtable introspectedtable) {
        
        try {
            abstractjavamappermethodgenerator methodgenerator = tmclass.newinstance();
            methodgenerator.setcontext(context);
            methodgenerator.setintrospectedtable(introspectedtable);
            methodgenerator.addinterfaceelements(interfaze);
            
        } catch (instantiationexception | illegalaccessexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
        

        return super.clientgenerated(interfaze, toplevelclass, introspectedtable);
    }

    @override
    public boolean validate(list<string> warnings) {
        // todo auto-generated method stub
        return true;
    }

}
view code

  代码比较简单,主要是重写了sqlmapdocumentgenerated(生成mapper xml方法)、clientgenerated(生成mapper 接口方法),在这里面我通过把指定泛型类型(分别继承自 abstractxmlelementgenerator、abstractjavamappermethodgenerator)加入到生成xml和接口的过程中,以实现生成过程的抽象。

  2.4.2.我这里由于默认生成的shoppingorderdetailmapper(实体类:shoppingorderdetail是购物订单详情)无法满足需要,我需要额外再增加两个方法:

  list<shoppingorderdetail> selectbyorderid(int shoppingorderid); 、void deletebyorderid(int shoppingorderid); 故在这里自定义继承自customappendmethodplugin的插件类:shoppingorderdetailmapperplugin,具体实现代码如下:

package cn.zuowenjun.boot.mybatis.plugin;

import java.util.set;
import java.util.treeset;

import org.mybatis.generator.api.dom.java.fullyqualifiedjavatype;
import org.mybatis.generator.api.dom.java.interface;
import org.mybatis.generator.api.dom.java.javavisibility;
import org.mybatis.generator.api.dom.java.method;
import org.mybatis.generator.api.dom.java.parameter;
import org.mybatis.generator.api.dom.xml.attribute;
import org.mybatis.generator.api.dom.xml.textelement;
import org.mybatis.generator.api.dom.xml.xmlelement;
import org.mybatis.generator.codegen.mybatis3.javamapper.elements.abstractjavamappermethodgenerator;
import org.mybatis.generator.codegen.mybatis3.xmlmapper.elements.abstractxmlelementgenerator;

/*
 * ref see https://www.cnblogs.com/se7end/p/9293755.html
 * author:zuowenjun
 * date:2019-1-29
 */
public class shoppingorderdetailmapperplugin 
extends customappendmethodplugin<shoppingorderdetailxmlelementgenerator, abstractjavamappermethodgenerator> {

    public shoppingorderdetailmapperplugin() {
        super(shoppingorderdetailxmlelementgenerator.class,shoppingorderdetailjavamappermethodgenerator.class);
    }

}


class shoppingorderdetailxmlelementgenerator extends abstractxmlelementgenerator{

    @override
    public void addelements(xmlelement parentelement) {
        
        if(!introspectedtable.getaliasedfullyqualifiedtablenameatruntime().equalsignorecase("ta_testshoppingorderdetail")) {
            return;
        }

        textelement selecttext = new textelement("select * from " + introspectedtable.getaliasedfullyqualifiedtablenameatruntime()
        + " where shoppingorderid=#{shoppingorderid}");
        
         xmlelement selectbyorderid = new xmlelement("select");
         selectbyorderid.addattribute(new attribute("id", "selectbyorderid"));
         selectbyorderid.addattribute(new attribute("resultmap", "baseresultmap"));
         selectbyorderid.addattribute(new attribute("parametertype", "int"));
         selectbyorderid.addelement(selecttext);
         parentelement.addelement(selectbyorderid);
         
            textelement deletetext = new textelement("delete from " + introspectedtable.getaliasedfullyqualifiedtablenameatruntime()
            + " where shoppingorderid=#{shoppingorderid}");
            
             xmlelement deletebyorderid = new xmlelement("delete");
             deletebyorderid.addattribute(new attribute("id", "deletebyorderid"));
             deletebyorderid.addattribute(new attribute("parametertype", "int"));
             deletebyorderid.addelement(deletetext);
             parentelement.addelement(deletebyorderid);
    }
    
}


class shoppingorderdetailjavamappermethodgenerator extends abstractjavamappermethodgenerator{

    @override
    public void addinterfaceelements(interface interfaze) {
        
        if(!introspectedtable.getaliasedfullyqualifiedtablenameatruntime().equalsignorecase("ta_testshoppingorderdetail")) {
            return;
        }
        
        addinterfaceselectbyorderid(interfaze);
        addinterfacedeletebyorderid(interfaze);
    }
    
       private void addinterfaceselectbyorderid(interface interfaze) {
            // 先创建import对象
            set<fullyqualifiedjavatype> importedtypes = new treeset<fullyqualifiedjavatype>();
            // 添加lsit的包
            importedtypes.add(fullyqualifiedjavatype.getnewlistinstance());
            // 创建方法对象
            method method = new method();
            // 设置该方法为public
            method.setvisibility(javavisibility.public);
            // 设置返回类型是list
            fullyqualifiedjavatype returntype = fullyqualifiedjavatype.getnewlistinstance();
            fullyqualifiedjavatype listargtype = new fullyqualifiedjavatype(introspectedtable.getbaserecordtype());
            returntype.addtypeargument(listargtype);
            
            // 方法对象设置返回类型对象
            method.setreturntype(returntype);
            // 设置方法名称为我们在introspectedtable类中初始化的 “selectbyorderid”
            method.setname("selectbyorderid");

            // 设置参数类型是int类型
            fullyqualifiedjavatype parametertype;
            parametertype = fullyqualifiedjavatype.getintinstance();
            // import参数类型对象(基本类型其实可以不必引入包名)
            //importedtypes.add(parametertype);
            // 为方法添加参数,变量名称record
            method.addparameter(new parameter(parametertype, "shoppingorderid")); //$non-nls-1$
            //
            context.getcommentgenerator().addgeneralmethodcomment(method, introspectedtable);
            if (context.getplugins().clientselectbyprimarykeymethodgenerated(method, interfaze, introspectedtable)) {
                interfaze.addimportedtypes(importedtypes);
                interfaze.addmethod(method);
            }
        }
       
       private void addinterfacedeletebyorderid(interface interfaze) {
            // 创建方法对象
            method method = new method();
            // 设置该方法为public
            method.setvisibility(javavisibility.public);
            // 设置方法名称为我们在introspectedtable类中初始化的 “deletebyorderid”
            method.setname("deletebyorderid");
            // 设置参数类型是int类型
            fullyqualifiedjavatype parametertype;
            parametertype = fullyqualifiedjavatype.getintinstance();
            method.addparameter(new parameter(parametertype, "shoppingorderid")); //$non-nls-1$
            
            context.getcommentgenerator().addgeneralmethodcomment(method, introspectedtable);
            if (context.getplugins().clientselectbyprimarykeymethodgenerated(method, interfaze, introspectedtable)) {
                interfaze.addmethod(method);
            }
            
       }
        
    
}

从如上代码所示,核心点是自定义继承自abstractxmlelementgenerator、abstractjavamappermethodgenerator的shoppingorderdetailxmlelementgenerator(xml生成器类)、shoppingorderdetailjavamappermethodgenerator(mapper接口生成器类),然后分别在addelements、addinterfaceelements添加自定义生成xml及接口方法的逻辑(如上代码中使用的是反射,若想学习了解反射请自行网上查找相关资料,c#也有反射哦,应该好理解),注意由于插件在生成过程中每个实体类都会调用一次,故必需作相应的判断(判断当前要附加的自定义方法是符与当前实体类生成过程相符,如果不相符则忽略退出)

如下是shoppingorderdetail实体类的代码:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
package cn.zuowenjun.boot.domain;

import java.math.bigdecimal;
import java.util.date;

public class shoppingorderdetail {
    private integer id;

    private integer shoppingorderid;

    private integer goodsid;

    private integer qty;

    private bigdecimal totalprice;

    private string createby;

    private date createtime;

    public integer getid() {
        return id;
    }

    public void setid(integer id) {
        this.id = id;
    }

    public integer getshoppingorderid() {
        return shoppingorderid;
    }

    public void setshoppingorderid(integer shoppingorderid) {
        this.shoppingorderid = shoppingorderid;
    }

    public integer getgoodsid() {
        return goodsid;
    }

    public void setgoodsid(integer goodsid) {
        this.goodsid = goodsid;
    }

    public integer getqty() {
        return qty;
    }

    public void setqty(integer qty) {
        this.qty = qty;
    }

    public bigdecimal gettotalprice() {
        return totalprice;
    }

    public void settotalprice(bigdecimal totalprice) {
        this.totalprice = totalprice;
    }

    public string getcreateby() {
        return createby;
    }

    public void setcreateby(string createby) {
        this.createby = createby == null ? null : createby.trim();
    }

    public date getcreatetime() {
        return createtime;
    }

    public void setcreatetime(date createtime) {
        this.createtime = createtime;
    }
}
view code

另外顺便解决一个踩坑点:上面提到了,我们在pom文件配置mybatis-generator-maven-plugin插件时,overwrite设为true,目的是确保每次执行生成时,生成的代码能够覆盖已经存在的,理想是美好的,但现实总会有点小意外,我们这样配置,只能解决生成的mapper 接口类文件不会重复,但生成的mapper xml文件仍然会附加代码导致重复,故我们需要解决这个问题,而解决这个问题的关键是:generatedxmlfile.ismergeable,如果ismergeable为true则会合并,目前默认都是false,所以我们只需实现将generatedxmlfile.ismergeable设为true即可,由于ismergeable是私有字段,只能采取插件+反射动态改变这个值了,自定义合并代码插件overismergeableplugin实现如下:

package cn.zuowenjun.boot.mybatis.plugin;

import java.lang.reflect.field;
import java.util.list;

import org.mybatis.generator.api.generatedxmlfile;
import org.mybatis.generator.api.introspectedtable;
import org.mybatis.generator.api.pluginadapter;

/*
 * 修复mybatis-generator重复执行时生成的xml有重复代码(核心:ismergeable=false)
 * author:https://blog.csdn.net/zengqiang1/article/details/79381418
 * editor:zuowenjun
 */
public class overismergeableplugin extends pluginadapter {

    @override
    public boolean validate(list<string> warnings) {
        return true;
    }
    

    @override
    public boolean sqlmapgenerated(generatedxmlfile sqlmap,
            introspectedtable introspectedtable) {
        
          try {
              field field = sqlmap.getclass().getdeclaredfield("ismergeable");
              field.setaccessible(true);
              field.setboolean(sqlmap, false);
          } catch (exception e) {
              e.printstacktrace();
          }
        
        return true;
    }

}

2.4.3.在generatorconfig.xml配置文件中增加plugin配置,如下:

        <plugin type="cn.zuowenjun.boot.mybatis.plugin.overismergeableplugin"></plugin>
        <plugin type="cn.zuowenjun.boot.mybatis.plugin.shoppingorderdetailmapperplugin"></plugin>

... ...省略中间过程

        <table tablename="ta_testshoppingorderdetail"
            domainobjectname="shoppingorderdetail">
            <generatedkey column="id" sqlstatement="jdbc" identity="true" />
        </table>

2.4.4.由于不能在同一个项目中直接使用plugin类(具体原因请上网查询,在此了解即可),故还需把cn.zuowenjun.boot.mybatis.plugin这个包中的文件单独导出生成jar包,然后把这个jar包复制到项目的指定目录下(本示例是放在libs目录下),然后再在pom为mybatis-generator-maven-plugin单独添加system本地依赖才行,maven添加依赖如下:

            <plugin>
                <!--ref: https://gitee.com/free/mybatis_utils/blob/master/mybatisgeneator/mybatisgeneator.md -->
                <!--ref: https://www.cnblogs.com/handsomeye/p/6268513.html -->
                <groupid>org.mybatis.generator</groupid>
                <artifactid>mybatis-generator-maven-plugin</artifactid>
                <version>1.3.7</version>
                <configuration>
                    <configurationfile>src/main/resources/mybatis/generatorconfig.xml</configurationfile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
                <dependencies>
                    <!-- 为mybatis-generator增加自定义插件依赖 -->
                    <dependency>
                        <groupid>cn.zuowenjun.boot.mybatis.plugin</groupid>
                        <artifactid>cn.zuowenjun.boot.mybatis.plugin</artifactid>
                        <version>1.0</version>
                        <scope>system</scope>
                        <systempath>${basedir}/src/main/libs/cn.zuowenjun.boot.mybatis.plugin.jar</systempath>
                    </dependency>
                </dependencies>
            </plugin>

如果4步完成后,最后执行maven buid的生成mybatis代码过程即可,最后查看生成的mapper及xml都会有对应的自定义方法,在此就不再贴出结果了。

  2.5进阶用法:利用mybatis的继承机制实现添加额外自定义方法

  如2.4节所述,我们可以通过自定义plugin来实现添加额外自定义的方法,而且不用担心被覆盖,但可能实现有点麻烦(里面用到了反射),有没有简单一点的办法呢?当然有,即可以先使用mybatis generator框架生成默代代码,然后再结合使用2.2所述方法(手写mapper接口类及mapper xml),利用mapper xml的继承特性完成添加自定义方法的过程中,具体步骤与2.2相同,在此贴出(注意前提是先自动生成代码,然后再操作如下步骤)

  2.5.1.定义扩展mapper接口类(shoppingorderextmapper,扩展shoppingordermapper,它们之间无需继承),代码如下:(很简单,就是定义了一个特殊用途的方法)

package cn.zuowenjun.boot.mapper;

import java.util.list;

import cn.zuowenjun.boot.domain.shoppingorder;

public interface shoppingorderextmapper {
    
    list<shoppingorder> selectallbyshopper(string shopper);
}

  2.5.2.编写对应的shoppingorderextmapper.xml,这里面就要用到继承,继承主要是resultmap【实现继承用:extends=要继承的mapper xml resultmap】,这样就不用两个地方都为一个实体类写结果映射配置了,其余的都按一个新的mapper xml配置来设计即可,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.zuowenjun.boot.mapper.shoppingorderextmapper">
    <resultmap id="baseresultmap" type="cn.zuowenjun.boot.domain.shoppingorder" 
    extends="cn.zuowenjun.boot.mapper.shoppingordermapper.baseresultmap">
    </resultmap>
    <select id="selectallbyshopper" resultmap="baseresultmap" parametertype="string">
        select * from ta_testshoppingorder where shopper=#{shopper}
    </select>
</mapper>

如上两步即完成扩展添加额外自定义的方法,又不用担心重复执行生成代码会被覆盖掉,只是使用时需要单独注册到spring,单独实例,虽不完美但弥补了默认生成代码的不足也是可行的。

  2.6 使用springboottest + junit测试基于mybatis框架实现的dao类

   在此不详情说明junit测试的用法,网上大把资源,只是单独说明结合springboottest 注解,完成单元测试,先看单元测试代码:

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
package cn.zuowenjun.springbootdemo;


import java.math.bigdecimal;
import java.util.date;
import java.util.list;

import org.junit.assert;
import org.junit.test;
import org.junit.runner.runwith;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.test.context.springboottest;
import org.springframework.test.annotation.rollback;
import org.springframework.test.context.junit4.springrunner;
import org.springframework.transaction.annotation.transactional;

import cn.zuowenjun.boot.springbootdemoapplication;
import cn.zuowenjun.boot.domain.*;
import cn.zuowenjun.boot.mapper.goodsmapper;
import cn.zuowenjun.boot.mapper.shoppingorderdetailmapper;
import cn.zuowenjun.boot.mapper.shoppingordermapper;

@runwith(springrunner.class)
@springboottest(classes=springbootdemoapplication.class)
public class shoppingordermappertests {

    @autowired
    private shoppingordermapper shoppingordermapper;
    
    @autowired
    private shoppingorderdetailmapper shoppingorderdetailmapper;
    
    @autowired
    private goodsmapper goodsmapper;
    
    @transactional
    @rollback(false) //不加这个,默认测试完后自动回滚
    @test
    public void testinsertshoppingorder() {

        goods goods= goodsmapper.get(1);
        
        shoppingorder shoppingorder=new shoppingorder();
        shoppingorder.setshopper("zuowenjun");
        shoppingorder.setiscompleted(false);
        shoppingorder.settotalprice(bigdecimal.valueof(0));
        shoppingorder.settotalqty(1);
        shoppingorder.setcreateby("zuowenjun");
        shoppingorder.setcreatetime(new date());
        
        int orderid= shoppingordermapper.insert(shoppingorder);
        shoppingorder.setid(orderid);
        
        shoppingorderdetail shoppingorderdetail=new shoppingorderdetail();
        shoppingorderdetail.setgoodsid(goods.getid());
        shoppingorderdetail.setshoppingorderid(shoppingorder.getid());
        shoppingorderdetail.setqty(10);
        shoppingorderdetail.settotalprice(bigdecimal.valueof(shoppingorderdetail.getqty()).multiply(goods.getprice()));
        shoppingorderdetail.setcreateby("zuowenjun");
        shoppingorderdetail.setcreatetime(new date());
        
        shoppingorderdetailmapper.insert(shoppingorderdetail);
        
        list<shoppingorderdetail> orderdetails= shoppingorderdetailmapper.selectbyorderid(shoppingorder.getid());
        if(orderdetails!=null && orderdetails.size()>0) {
            for(shoppingorderdetail od:orderdetails) {
                system.out.println("id:" + od.getid() + ",goodsid:" + od.getgoodsid());
            }
        }
        
        assert.asserttrue(orderdetails.size()>0); 
    }
}
view code

  与junit单元测试用法基本相同,唯 一的区别就是在单元测试的类上添加@springboottest,并指定启动类(如代码中所示:@springboottest(classes=springbootdemoapplication.class)),另外注意一点:如果测试方法使用@transactional注解,那么当测试完成后会回滚(即并不会提交事务),如果想完成事务的提交,则需如代码中所示添加@rollback(false),其中false指不回滚,true则为回滚。

三、简单演示集成thymeleaf模板引擎(这里只是用一个简单的页面演示效果,由于现在都流行前后端分离,故只需了解即可)

  说明:thymeleaf是spring mvc的端视图引擎,与jsp视图引擎类似,只不过在spring boot项目中默认支持thymeleaf(thymeleaf最大的优点是视图中不含java代码,不影响ui美工及前端设计),而jsp不建议使用,当然也可以通过添加相关的jsp的jar包依赖,实现jsp视图,具体请自行网上查找资源,同时spring mvc +jsp视图的用法可以参见该系列的上篇文章

  3.1.添加thymeleaf的maven依赖,pom配置如下:

        <!-- 添加thymeleaf模板引擎(用于springmvc模式,如果是rest api项目,则无需引用) -->
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-thymeleaf</artifactid>
        </dependency>

  3.2.编写后端controller,以便响应用户请求,代码如下:(这个与普通spring mvc+jsp相同,区别在view)

package cn.zuowenjun.boot.controller;

import java.util.list;

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.controller;
import org.springframework.ui.model;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.requestmapping;

import cn.zuowenjun.boot.domain.*;
import cn.zuowenjun.boot.service.*;

@controller
@requestmapping("/test")
public class testcontroller {
    
    @autowired
    private shopuserservice shopuserservice;
    
    @getmapping("/userlist")
    public string list(model model) {
        
        list<shopuser> users= shopuserservice.getall();
        model.addattribute("title", "测试使用thymeleaf模板引擎展示数据");
        model.addattribute("users", users);
        
        //可以在application.properties添加如下配置,以改变thymeleaf的默认设置
        //spring.thymeleaf.prefix="classpath:/templates/" 模板查找路径
        //spring.thymeleaf.suffix=".html" 模板后缀名
        
        return "/test";//默认自动查找路径:src/main/resources/templates/*.html
    }
}

  3.3编写前端视图html模板页面,最后演示效果

   html视图页面代码:(th:xxx为thymeleaf的模板特有的标识符,${xxx}这是sp el表达式,这个之前讲过的,很简单,不展开说明)

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>test user list -power by thymeleaf</title>
<style type="text/css">
    table{
        border:2px solid blue;
        border-collapse:collapse;
        width

                    
                
(0)
打赏 JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识 微信扫一扫

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
验证码: JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识