Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

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

梦在旅途 2019-02-13 14:22:00 阅读数:266 评论数:0 点赞数:0 收藏数:0

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插件来创建,可参见:https://www.cnblogs.com/shaoniandream/p/9679942.htmlhttps://blog.csdn.net/qq_32572497/article/details/62037873

设置后点击页面的生成项目按钮,即可生成并下载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 classSpringbootdemoApplication {public static voidmain(String[] args) { SpringApplication.run(SpringbootdemoApplication.class, args); } }

1.2.2.解决POM文件报:

Description Resource Path Location TypeExecution 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依赖: org.apache.maven.plugins maven-resources-plugin 2.5 maven-plugin

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

org.springframework.boot spring-boot-devtools true org.springframework.boot spring-boot-maven-plugin true

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

1.3演示请求REST API分别返回JSON、XML

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

  1.3.1在cn.zuowenjun.boot.controller包中创建DemoController,并编写hellojson、helloxml Action方法,代码如下:packagecn.zuowenjun.boot.controller;import org.springframework.web.bind.annotation./;import cn.zuowenjun.boot.domain./; @RestControllerpublic classDemoController { @RequestMapping(value="/hello/json",produces="application/json;charset=utf-8")publicHelloDto hellojson() { HelloDto dto=newHelloDto(); dto.setMessage("hello,zuowenjun.cn,hello java spring boot!");returndto; } @RequestMapping(value="/hello/xml",produces="text/xml;charset=utf-8")publicHelloDto helloxml() { HelloDto dto=newHelloDto(); dto.setMessage("hello,zuowenjun.cn,hello java spring boot!");returndto; } }

如上代码简要说明:@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中的默认版本,当然也可以强制指定版本) com.fasterxml.jackson.jaxrs jackson-jaxrs-xml-provider [2.5.0,)

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

效果如下:

     

二、使用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依赖包,配置如下:

org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2

2.1全手写JAVA代码实现Mybatis的CRUD;

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

packagecn.zuowenjun.boot.domain;importjava.math.BigDecimal;importjava.util.Date;public classGoods {private intid;privateString title;privateString picture;privateBigDecimal price;privateString introduction;private intcategoryId;privateString lastEditBy;privateDate lastEditTime;publicGoods() { }public Goods(intid,String title,String picture, BigDecimal price,String introduction,intcategoryId,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 intgetId() {returnid; }public void setId(intid) {this.id =id; }publicString getTitle() {returntitle; }public voidsetTitle(String title) {this.title =title; }publicString getPicture() {returnpicture; }public voidsetPicture(String picture) {this.picture =picture; }publicBigDecimal getPrice() {returnprice; }public voidsetPrice(BigDecimal price) {this.price =price; }publicString getIntroduction() {returnintroduction; }public voidsetIntroduction(String introduction) {this.introduction =introduction; }public intgetCategoryId() {returncategoryId; }public void setCategoryId(intcategoryId) {this.categoryId =categoryId; }publicString getLastEditBy() {returnlastEditBy; }public voidsetLastEditBy(String lastEditBy) {this.lastEditBy =lastEditBy; }publicDate getLastEditTime() {returnlastEditTime; }public voidsetLastEditTime(Date lastEditTime) {this.lastEditTime =lastEditTime; } }View Code

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

packagecn.zuowenjun.boot.mapper;import java.util./;import org.apache.ibatis.annotations./;import cn.zuowenjun.boot.domain./;public interfaceGoodsMapper { @Select("select / from TATestGoods order by id offset (${pageNo}-1)/${pageSize} rows fetch next ${pageSize} rows only") List getListByPage(int pageSize,intpageNo); @Select("select / from TATestGoods where categoryId=/#{categoryId} order by id") List getList(intcategoryId); @Select("") List getListByMultIds(@Param("ids")int...ids); @Select("select / from TATestGoods where id=/#{id}") Goods get(intid); @Insert(value="insert into TATestGoods(title, picture, price, introduction, categoryId, " + "lastEditBy, lastEditTime) values(/#{title},/#{picture},/#{price},/#{introduction},/#{categoryId},/#{lastEditBy},getdate())") @Options(useGeneratedKeys=true,keyProperty="id",keyColumn="id")voidinsert(Goods goods); @Delete(value="delete from TATestGoods where id=/#{id}")void delete(intid); @Update("update TATestGoods set title=/#{title},picture=/#{picture},price=/#{price},introduction=/#{introduction}," + "categoryId=/#{categoryId},lastEditBy=/#{lastEditBy},lastEditTime=getdate() " + "where id=/#{id}")voidupdate(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注解中使用格式实现,如果想用实现复杂的一对一,一对多,多对多等复杂的查询,则需要添加results注解并指定相应的关联关系,同时select SQL语句也应关联查询,可参见:https://blog.csdn.net/desert568/article/details/79079151

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

2.2全手写AVA代码+Mapper XML实现Mybatis的CRUD;

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

packagecn.zuowenjun.boot.domain;importjava.util.Date;public classShoppingCart {private intid;privateString shopper;private intgoodsId;private intqty;privateDate addedTime;privateGoods inGoods;publicShoppingCart() { }public ShoppingCart(int id,String shopper,int goodsId,intqty,Date addedTime) {this.id=id;this.shopper=shopper;this.goodsId=goodsId;this.qty=qty;this.addedTime=addedTime; }public intgetId() {returnid; }public void setId(intid) {this.id =id; }publicString getShopper() {returnshopper; }public voidsetShopper(String shopper) {this.shopper =shopper; }public intgetGoodsId() {returngoodsId; }public void setGoodsId(intgoodsId) {this.goodsId =goodsId; }public intgetQty() {returnqty; }public void setQty(intqty) {this.qty =qty; }publicDate getAddedTime() {returnaddedTime; }public voidsetAddedTime(Date addedTime) {this.addedTime =addedTime; }publicGoods getInGoods() {returninGoods; }public voidsetInGoods(Goods inGoods) {this.inGoods =inGoods; } }View Code

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

packagecn.zuowenjun.boot.mapper;importjava.util.List;importorg.apache.ibatis.annotations.Param;import cn.zuowenjun.boot.domain./*;public interfaceShoppingCartMapper { ListgetList(String shopper);voidinsert(ShoppingCart shoppingCart);voidupdate(ShoppingCart shoppingCart);void deleteItem(intid);voiddelete(String shopper);intgetBuyCount(String shopper); ShoppingCart get(@Param("shopper") String shopper,@Param("goodsId") intgoodsId); }

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

2.2.3.在mybatis.mapper-locations设置的mapper xml存放的路径中创建XML文件,并手动编写映射的SQL语句,如下所示: select / from TATestShoppingCart a inner join TATestGoods b on a.goodsId=b.id where shopper=/#{shopper} order by addedTime select count(1) from (select goodsId from TA_TestShoppingCart where shopper=/#{shopper} group by goodsId) as t select / from TATestShoppingCart a inner join TATestGoods b on a.goodsId=b.id where shopper=/#{shopper} and goodsId=/#{goodsId} insert into TATestShoppingCart(shopper, goodsId, qty, addedTime) values(/#{shopper},/#{goodsId},/#{qty},getdate()) update TATestShoppingCart set shopper=/#{shopper},goodsId=/#{goodsId},qty=/#{qty},addedTime=getdate() where id=/#{id} delete from TATestShoppingCart where id=/#{id} delete from TATestShoppingCart where shopper=/#{shopper}

如上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配置详见:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

以上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包依赖,如下所示: com.microsoft.sqlserver mssql-jdbc 7.0.0.jre8 org.mybatis.generator mybatis-generator-core 1.3.7

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

org.mybatis.generator mybatis-generator-maven-plugin 1.3.7 src/main/resources/mybatis/generatorconfig.xml true true

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

packagecn.zuowenjun.boot.domain;importjava.math.BigDecimal;importjava.util.Date;public classShoppingOrder {privateInteger id;privateString shopper;privateInteger totalqty;privateBigDecimal totalprice;privateBoolean iscompleted;privateString createby;privateDate createtime;publicInteger getId() {returnid; }public voidsetId(Integer id) {this.id =id; }publicString getShopper() {returnshopper; }public voidsetShopper(String shopper) {this.shopper = shopper == null ? null: shopper.trim(); }publicInteger getTotalqty() {returntotalqty; }public voidsetTotalqty(Integer totalqty) {this.totalqty =totalqty; }publicBigDecimal getTotalprice() {returntotalprice; }public voidsetTotalprice(BigDecimal totalprice) {this.totalprice =totalprice; }publicBoolean getIscompleted() {returniscompleted; }public voidsetIscompleted(Boolean iscompleted) {this.iscompleted =iscompleted; }publicString getCreateby() {returncreateby; }public voidsetCreateby(String createby) {this.createby = createby == null ? null: createby.trim(); }publicDate getCreatetime() {returncreatetime; }public voidsetCreatetime(Date createtime) {this.createtime =createtime; } }View Code

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

10.dtd">

版权声明
本文为[梦在旅途]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/zuowj/p/10335080.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领