idea整合spring boot+spring mvc+mybatis框架

1. 前言

前面文章整合过了ssm的,是相对spring的,不过在现在微服务流行之际,为了往后面的springcloud发展学习,先学习一下springboot,在学习的过程中用spring boot+spring mvc+mybatis进行搭建接口平台。

2. 简介

spring boot:Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。(来自百度百科)。

2.1 spring boot特点

  1. 创建独立的Spring应用程序
  2. 嵌入的Tomcat,无需部署WAR文件
  3. 开箱即用,提供各种默认配置来简化项目配置
  4. 没有冗余代码生成和XML配置的要求

2.2 个人理解

在我看来,spring boot并不是什么新的框架,它只是默认配置了很多框架的使用方式;类似于maven整合了jar,而spring boot整合了很多的框架。从本质上来讲,spring boot就是spring,它做了那些你需要去做的复杂配置。它使用“习惯优于配置”的理念让你的项目快速运行起来。

2.2 回顾一下spring web项目步骤

  1. 配置web.xml,加载spring和spring mvc
  2. 配置数据库连接、配置spring事务
  3. 配置加载配置文件的读取,开启注解
  4. 配置日志文件
    ......
    配置完成后部署tomcat调试...

2.3 spring boot项目

只需要非常少的几个配置就可以迅速方便的搭建起来一套web项目或者是构建一个微服务!下面就让我们一起来领略spring boot的魅力

3. 项目搭建

整个项目使用maven构建,有关idea集成maven、jdk、tomcat等可翻我上一篇文章。

3.1 在这里使用spring提供的SPRING INITIALIZR工具来产生基础项目。

  1. 访问 :http://start.spring.io/
  2. 选择构建工具maven、语言java、版本1.5.10(支持jdk1.7)
initializr.png
  1. 点击Generate Project下载项目压缩包
  2. 解压项目,导入进idea,说一下简要步骤
  1. File -> New -> Project from Existing Sources
  2. 选择你解压的项目文件夹
  3. 点击OK
  4. 选择Import project from external model并选择Maven,点击Next到底为止。

3.2 编译错误

若在项目编译过程中,遇到[Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8]这个错误,可按照如下更改,这里我统一改为了1.7

1,Project Structure里确认两个地方:Project sdk以及project language level
2,Project Structure->Modules里Sources里的Language level
3,Preferences->java Compiler->Per-module bytecode Version

至此基础项目准备完毕,运行一下项目

image.png

看见Spring Boot这个图案证明基础项目搭建成功。

4. 编写代码

4.1 项目结构

项目结构.png

系统整个架构为springboot+springmvc+mybatis,restful的接口风格。只是一个示例项目,也没有进行模块分包。整个结构的话还是controller、service、dao的三层结构。在这里面dao层多写了一个接口和实现。对于service层没有写接口,因为我觉得简单的业务没必要写接口(包括这里的dao也是)。
我也一直在思考,对于service和dao层,到底需不需要接口和实现。网上查了一些,有些是瞎扯了一堆“接口和实现分离”、“面向接口编程”、“设计模式”、“解耦”等,但是也没说出个所以然;有些是说没必要分离,或者看系统架构。自己也是经历不多,不知道确切的区别或者说有什么效率上的区别。这个待我日后慢慢积累,有机会咨询长者学习,或者评论区静待大神的解答。

4.2 项目配置

springboot 遵循"习惯优于配置"原则,使用Spirng Boot只需很少的配置,大部分时候可以使用默认配置。
使用INITIALIZR工具创建的springboot项目,默认会在resource目录下创建application.properties文件,另外也可以使用yml类型的配置文件代替properties文件。在这里我是使用的是yml文件。

application.yml

spring:
  datasource:
        # 驱动配置信息
        url: jdbc:mysql://localhost:3306/spring_boot?useUnicode=true&characterEncoding=utf8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        
        # 连接池的配置信息
        filters: stat
        maxActive: 20
        initialSize: 1
        maxWait: 60000
        minIdle: 1
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: select 'x'
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxOpenPreparedStatements: 20

这里主要就是配置了阿里的druid连接池信息。上面的就是类型和驱动这些,然后就是mysql数据库的url、用户名和密码,相应改成自己的就行。下面的是druid的参数配置项,这里随便设置了一些,具体可详查Druid。

mybatis-config.xml





    
        
         
         
         
    

    
         
    


这个配置主要就是关于mybatis的配置了,这里就提两点,一个是setting里面的logImpl配置,可以把执行的sql语句打印在控制台,便于排查sql错误;二个是使用typeAliases标签元素来对类型进行别名控制,也就是给具体的实体类一个别名,不用写完整路径。具体使用在后面mapper中会讲到。

以上就是这个项目目前用到的两个配置了,是不是比起spring来说简便多了。

pom.xml



    4.0.0

    com.bgy
    springboot
    0.0.1-SNAPSHOT
    jar

    springboot
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.10.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.7
    

    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            
            org.springframework.boot
            spring-boot-starter-web
            
                
                    spring-boot-starter-logging
                    org.springframework.boot
                
            
        
        
        
            org.springframework.boot
            spring-boot-starter-log4j2
        
        
        
            org.springframework.boot
            spring-boot-starter-web
            1.3.6.RELEASE
        
        
        
            com.alibaba
            druid
            1.0.11
        
        
        
            mysql
            mysql-connector-java
        
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.0
        
        
        
            org.springframework.boot
            spring-boot-starter-redis
            1.3.8.RELEASE
        
        
        
            com.alibaba
            fastjson
            1.1.27
        
        
            com.google.code.gson
            gson
        
        
        
            org.springframework.boot
            spring-boot-starter-aop
        
        
            net.minidev
            json-smart
            RELEASE
        
    

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



这些就是当前项目中用到的一些maven依赖了。

DbDataSource.class

@Configuration
@MapperScan(basePackages = "com.bgy.springboot.dao",sqlSessionTemplateRef = "dbSqlSessionTemplate")
public class DbDataSource {

    @Bean(name="dbData")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dbDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dbSqlSessionFactory")
    public SqlSessionFactory dbSqlSessionFactory(@Qualifier("dbData") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setConfigLocation( new ClassPathResource("mybatis-config.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name="dbSqlSessionTemplate")
    public SqlSessionTemplate dbSqlSessionTemplate(@Qualifier("dbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception{
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "dbTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dbData") DataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }
}

SqlSessionTemplate是MyBatis提供的持久层访问模板化的工具,这个类负责管理MyBatis的SqlSession,用于调用MyBatis的SQL方法。因为SqlSessionTemplate是线程安全的,可以被多个DAO所共享使用,所以项目中只建立了一个SqlSessionTemplate。

在这里使用的是mybatis注解需要的配置。mybatis3开始支持java注解,使用java注解可以替代xml配置文件,简化代码。上面的代码中,使用@MapperScan来扫描注册mybatis数据库接口类,其中basePackages属性表明接口类所在的包,sqlSessionTemplateRef表明接口类使用的SqlSessionTemplate。

@Configuration 申明这是一个配置类相当于xml配置文件,@Bean表示这是一个Spring管理的bean。
@ConfigurationProperties用于装载yml的配置信息

这里面其他关于SqlSessionTemplate的用法和细节就不一一讲了,不明白的可百度学习一下SqlSessionTemplate。提一下setMapperLocations是用于加载以xml结尾的mapper配置文件,这里注意路径就行了,根路径是resources。setConfigLocation是加载mybatis的配置文件mybatis-config.xml。

4.3 数据库文件

这个在上篇文章已经介绍过作用,就是方便对sql语句的查阅和修改。

db_ddl.sql

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` VARCHAR (45) NOT  NULL ,
  `user_name` VARCHAR (100) ,
  `nick_name` VARCHAR (100),
  `password` CHAR (32),
  `email` VARCHAR (50),
  `phone` VARCHAR (50),
  `sex` ENUM('S_MALE','S_FEMALE','S_BM'),
  `status` ENUM('S_OFF','S_NORMAL'),
  `avatar` VARCHAR (100),
  `remarks` VARCHAR (200),
  `add_at` BIGINT,
  `update_at` BIGINT,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

这里表名和字段与上一篇文章相比修改了一些,因为看了《阿里巴巴 Java开发手册》中写道:

表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 说明:MYSQL在Windows下不区分大小写,但在Linux上默认区分大小写。因此,数据库名、表名、字段名都不允许出现任何大写字母,避免节外生枝。

4.4 实体类

建立一个MUser的实体类

MUser.class

public class MUser {
    private String id;

    private String userName;

    private String nickName;

    private String password;

    private String email;

    private String phone;

    private String sex;

    private String status;

    private String avatar;

    private String remarks;

    private Long addAt;

    public MUser(){}

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    public Long getAddAt() {
        return addAt;
    }

    public void setAddAt(Long addAt) {
        this.addAt = addAt;
    }
}

4.5 Controller

4.5.1 BaseController
public class BaseController {
    private static final long serialVersionUID = 6357869213649815390L;

    /**
     * @param fastJson
     */
    protected JSONObject json = new JSONObject();
    /**
     * fastjson JSONArray
     */
    protected JSONArray jsonArray = new JSONArray();
    /**
     * fastjson用法
     * 对象转json字符串 String json = json.toJSONString(对象);
     * 字符串转json对象 json =json.parseObject(jsonStr);
     * 字符串转java对象 Object object = JSON.parseObject(jsonStr, Object.class);
     * 字符串转list  List list = JSON.parseArray(jsonStr, Object.class);
     */
}
 
 

在这里抽出了一个BaseController的父类,可放置多个Controller都会用到的一些对象或方法,这个父类被子类Controller继承。目前此项目中的BaseController只放置了fastjson的两个对象,正常项目中肯定会有不少共有的对象或方法都可放置这里面。

4.5.2 UserController
@Controller
@RequestMapping("/user")
public class UserController extends BaseController {

    @Resource(name = "userService")
    private UserService userService;

    /**
     * 添加用户
     *
     * @param mUserJson
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseBody
    public String addUser(@RequestBody String mUserJson) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.addUser(mUserJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    /**
     * 通过用户名称获取用户
     *
     * @param userName
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/{userName}", method = RequestMethod.GET)
    @ResponseBody
    public String getUserByName(@PathVariable String userName) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.getUserByName(userName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    /**
     * 修改用户
     *
     * @param mUserJson
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseBody
    public String updateUser(@PathVariable("id") String id, @RequestBody String mUserJson) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.updateUser(id, mUserJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public String deleteUser(@PathVariable("id") String id) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.deleteUser(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }
}

这里使用springmvc 相关注解,集成restful风格的接口,具体注解和含义、及restful风格的理解可翻上一篇文章。
与上一篇略有不同的本项目使用的是@Resource注解注入bean。

关于@Resource和@Autowired:

  • 两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
  • @Autowired默认按类型装配(这个注解属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)
  • @Resource默认安装名称进行装配(这个注解属于J2EE的),名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找。
  • 在我个人推荐用@Resource,因为这个注解是属于J2EE的,减少了与spring的耦合,并且代码看起更优雅。若有高见,欢迎指教。

这个示例代码实现了增删改查四个基础功能,前后端完全以JSON字符串进行交互。(这里前后端以JSON字符串交互的方式有待商榷,以前认知是用JSON字符串便于统一风格;不过最近一年以来的学习和工作,现在会直接使用实体类进行接收对象,免去JSON转对象的步骤。)

4.6 Service

4.6.1 BaseService
public class BaseService {
    private static final long serialVersionUID = 6357869213649815390L;

    /**
     * 得到32位的uuid
     *
     * @return
     */
    public String get32UUID() {
        String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
        return uuid;
    }

    /**
     * @param fastJson
     */
    protected JSONObject json = new JSONObject();
    /**
     * fastjson JSONArray
     */
    protected JSONArray jsonArray = new JSONArray();
    /**
     * fastjson用法
     * 对象转json字符串 String json = json.toJSONString(对象);
     * 字符串转json对象 json =json.parseObject(jsonStr);
     * 字符串转java对象 Object object = JSON.parseObject(jsonStr, Object.class);
     * 字符串转list  List list = JSON.parseArray(jsonStr, Object.class);
     */
}
 
 

也是抽出了一个父类BaseService,放置共用的对象或方法。这里虽然与BashController内容相似,不过没有与BaseController共用,因为想到如果项目复杂的话,Controller与Service层共用的东西会有较大差别。

4.6.2 UserService
@Service("userService")
public class UserService extends BaseService {

    @Resource(name = "userDaoImpl")
    private IUserDao iUserDao;


    /**
     * 添加用户
     *
     * @param mUserJson
     * @return
     */
    public String addUser(String mUserJson) {
        BgyResult br = new BgyResult();
        MUser mUser = json.parseObject(mUserJson, MUser.class);
        int count = iUserDao.countUserName(mUser);
        if (count > 0) {
            br.setCode("400");
            br.setMsg("用户名已存在");
            return json.toJSONString(br);
        }
        mUser.setId(get32UUID());
        boolean result = iUserDao.addUser(mUser);
        if (result) {
            br.setCode("200");
            br.setMsg("注册成功");
            br.setData(mUser);
        } else {
            br.setCode("400");
            br.setMsg("注册失败");
        }
        return json.toJSONString(br);
    }

    /**
     * 通过用户名获取用户
     *
     * @param userName
     * @return
     */
    public String getUserByName(String userName) {
        BgyResult br = new BgyResult();
        MUser mUser = iUserDao.getUserByName(userName);
        br.setCode("200");
        br.setMsg("Ok");
        br.setData(mUser);
        return json.toJSONString(br);
    }

    /**
     * 编辑用户
     *
     * @param mUserJson
     * @return
     */
    public String updateUser(String id, String mUserJson) {
        BgyResult br = new BgyResult();
        MUser mUser = json.parseObject(mUserJson, MUser.class);
        MUser myMUser = iUserDao.getUserById(id);
        if (myMUser == null) {
            br.setCode("400");
            br.setMsg("用户不存在");
            return json.toJSONString(br);
        }
        boolean result = iUserDao.updateUser(mUser);
        if (result) {
            br.setCode("200");
            br.setMsg("修改成功");
        } else {
            br.setCode("400");
            br.setMsg("修改失败");
        }
        return json.toJSONString(br);
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    public String deleteUser(String id) {
        BgyResult br = new BgyResult();
        MUser myMUser = iUserDao.getUserById(id);
        if (myMUser == null) {
            br.setCode("400");
            br.setMsg("用户不存在");
            return json.toJSONString(br);
        }
        boolean result = iUserDao.deleteUser(id);
        if (result) {
            br.setCode("200");
            br.setMsg("删除成功");
        } else {
            br.setCode("400");
            br.setMsg("删除失败");
        }
        return json.toJSONString(br);
    }
}

这一层主要就是处理业务逻辑了,没什么特别的地方,也是使用@Resource注入Bean。
这里用到了BgyResult类作为返回类。

4.7 BgyResult

public class BgyResult implements Serializable {
    private static final long serialVersionUID = 4832771715671880043L;
    private String code;
    private String msg;
    private Object data;

    public BgyResult(){
        this.code = "200";
        this.msg = "SUCCESS";
        this.data = null;
    }

    public BgyResult(String msg) {
        this.code = "400";
        this.msg = msg;
        this.data = null;
    }

    public BgyResult(String code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public String getCode() {
        return this.code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return this.msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return this.data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

为了统一与前端的交互,定义了BgyResult类进行标准返回,统一返回格式code、msg、data的json字符串。

4.8 Dao

4.8.1 IUserDao
public interface IUserDao {

    int countUserName(MUser mUser);

    boolean addUser(MUser mUser);

    MUser getUserByName(String userName);

    MUser getUserById(String id);

    boolean updateUser(MUser mUser);

    boolean deleteUser(String id);
}

这里就是dao的接口层,用于访问数据库,实现数据的持久化。这里提一下,《阿里巴巴Java开发手册》中写道:

接口类中的方法和属性不要加任何修饰符号(public也不要加),保持代码的简洁性。

4.8.2 UserDaoImpl
@Repository("userDaoImpl")
public class UserDaoImpl implements IUserDao {

    @Resource(name = "dbSqlSessionTemplate")
    private SqlSessionTemplate sqlSessionTemplate;

    @Override
    public int countUserName(MUser mUser) {
        return sqlSessionTemplate.selectOne("UserMapper.countUserName", mUser);
    }

    @Override
    public boolean addUser(MUser mUser) {
        int num = sqlSessionTemplate.insert("UserMapper.addUser", mUser);
        boolean result = false;
        if (num > 0) {
            result = true;
        }
        return result;
    }

    @Override
    public MUser getUserByName(String userName) {
        MUser mUser = sqlSessionTemplate.selectOne("UserMapper.getUserByName", userName);
        return mUser;
    }

    @Override
    public MUser getUserById(String id) {
        MUser mUser = sqlSessionTemplate.selectOne("UserMapper.getUserById", id);
        return mUser;
    }

    @Override
    public boolean updateUser(MUser mUser) {
        int num = sqlSessionTemplate.update("UserMapper.updateUser", mUser);
        boolean result = false;
        if (num > 0) {
            result = true;
        }
        return result;
    }

    @Override
    public boolean deleteUser(String id){
        int num = sqlSessionTemplate.update("UserMapper.deleteUser", id);
        boolean result = false;
        if (num > 0) {
            result = true;
        }
        return result;
    }
}

这个类就是dao接口的具体实现类了,没什么特别的。使用的是前面配置的SqlSessionTemplate模板化工具,与mapper.xml结合实现操作数据库。不过这里把所有返回int的操作做了一下boolean转换,便于service层处理。

4.9 UserMapper.xml





    
        
        
        
        
        
        
        
        
        
        
        
    

    

    
        INSERT INTO `user` (id,user_name,nick_name,password,email,phone,sex,status,avatar,remarks,add_at)
        VALUES (#{id},#{userName},#{nickName},#{password},#{email},#{phone},#{sex},#{status},#{avatar},#{remarks},unix_timestamp(now()),unix_timestamp(now()))
    

    

    

    
        UPDATE
        `user`
        SET
        
            nick_name = #{nickName},
        
        
            password = #{password},
        
        
            email = #{email},
        
        
            phone = #{phone},
        
        
            sex = #{sex},
        
        
            status = #{status},
        
        
            avatar = #{avatar},
        
        
            remarks = #{remarks},
        
        update_at = unix_timestamp(now())
        WHERE id = #{id}
    

    
        DELETE FROM `user` WHERE
        
            id = #{id} AND
        
        1=1
    

这个是mybatis中sql的映射文件。命名空间即是sqlSessionTemplate.insert("UserMapper.addUser", mUser)中的UserMapper

上面还提到了使用typeAliases标签元素来对类型进行别名控制,也就是给具体的实体类一个别名,不用写完整路径。在这里的type或者parameterType里写的MUser就是我们的实体类,如果不使用typeAliases,这里则应写完整路径,即
com.bgy.springboot.model.MUser

到此,整个项目的代码已经编写完成。实现了最基础的增删改查四个功能。

运行项目,测试一下试试。由于springboot内置了tomcat,所以不用单独放在tomcat中部署。直接运行SpringbootApplication类,即可运行项目。看见这个即表示运行成功:

run.png

下面以postman测试接口

添加用户

post.png

编辑用户

put.png

查询用户

get.png

删除用户

delete.png

至此,基于springboot+springmvc+mybatis框架的项目已经完全整合与测试通过。这个项目结合上一个项目的一些东西,当然也改进了一些东西。项目中涉及到的技术都没有难点,就算对于新手也很容易搞懂,也有完整的代码,已测试编译通过。

编者水平有限,若有错误或者更优的建议欢迎指出。

目前全部文章列表:
idea整合restful风格的ssm框架(一)
idea整合restful风格的ssm框架(二)
idea整合spring boot+spring mvc+mybatis框架
idea整合springboot+redis
JVM学习之—Java内存区域
JVM学习之—垃圾回收与内存分配策略
专题整理之—不可变对象与String的不可变
专题整理之—String的字符串常量池

你可能感兴趣的:(idea整合spring boot+spring mvc+mybatis框架)