1. 基本使用

访问 http://start.spring.io

默认的界面:

springboot整合easypoi 导出word eclipse导出springboot项目_spring

点击绿色按钮偏上方的 Switch to the full version. 链接可以展开完整界面,例如:

springboot整合easypoi 导出word eclipse导出springboot项目_User_02

然后,确定当前需要创建的项目的参数,主要是:

  • 顶部的项目类型、开发语言、SpringBoot版本;
  • Group,例如填写为com.springboot
  • Artifact,例如填写为sample
  • Name,表示项目名称,自动为Artifact的值,可以不更改;
  • Description:项目描述;
  • Package Name:项目的根包,在SpringBoot中,任何自定义组件都必须在根包或其子包中,例如控制器类、业务类等;
  • Packaging:WEB应用必须选择war;
  • Java Version:默认为8,也可以使用较低版本。

至此,项目的配置就已经完成,点击绿色的 Generate Project 按钮即可下载项目,得到项目的压缩包,将其解压,并剪切到Workspace中(这一步并不是必须的),然后在Eclipse中选择Import > Existing Maven Projects导入该项目,保证当前计算机是可以连接到Maven服务器,然后,项目会自动更新,添加所需要的所有依赖,至此,项目创建完成!

3. Hello, SpringBoot

设计目标:当输入某请求时,服务器返回"Hello, SpringBoot!"

在项目的根包下创建子包controller,然后创建控制器类,例如HelloController,然后,添加@RestController注解:

@RestController
public class HelloController {

}
@RestController也是一种@Controller,并且,表示该控制器类中所有处理请求的方法都是@ResponseBody的。使用这个注解后,处理请求也就不可以是转发或重定向了,如果一定要转发或重定向,必须使用原有@Controller注解,并且处理请求的方法上不可以添加@ResponseBody。

然后,添加处理请求的方法:

@RestController
public class HelloController {

    @GetMapping("/")
    public String sayHello() {
        return "Hello, SpringBoot!";
    }

}

至此,简单的HelloWorld就已经完成!

项目的根包下有SampleApplication类(类名中Application左侧的是项目的Artifact名,所以,不同的项目,该类的名称可能不同),该类是SpringBoot项目的启动类,直接以Run as > Java Application方式启动即可,启动时,控制台会有启动日志:

springboot整合easypoi 导出word eclipse导出springboot项目_mysql_03

其中,有一条:

Tomcat started on port(s): 8080 (http) with context path ''

SpringBoot是内置Tomcat的,所以,项目本身也不需要添加Tomcat运行环境,并且,SpringBoot部署项目时,如以上日志描述的,使用的Context Path是空值,以前访问时的URL可能是:

http://localhost:8080/项目名/

而在SpringBoot项目中则是:

http://localhost:8080/

也就是不需要再在URL中添加项目名了,执行效果例如:

springboot整合easypoi 导出word eclipse导出springboot项目_mysql_04

4. 关于静态资源

项目中的src\main\resources\下的static文件夹是专门用于存放静态资源的,例如图片等等:

springboot整合easypoi 导出word eclipse导出springboot项目_mysql_05

然后,启动SpringBoot,在浏览器中通过http://localhost:8080/timg.jpg即可访问:

springboot整合easypoi 导出word eclipse导出springboot项目_mysql_06

5. 整合MyBatis

如果在http://start.spring.io创建项目时,并没有添加MyBatis等依赖,则需要手动添加:

<!-- 整合MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.7</version>
</dependency>

然后,还需要添加数据库的驱动:

<!-- 数据库 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

注意:SpringBoot会自动使用最新版本的jar包,并不推荐自定义版本号,如果指定了版本,反而会提示警告:

springboot整合easypoi 导出word eclipse导出springboot项目_spring_07

然后,打开SpringBoot的配置文件src\main\resources\application.properties,添加数据库连接的相关配置:

spring.datasource.url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root

以上配置,将由SpringBoot自动读取,并注入到数据源对象中,所以,以上配置的各属性名必须是以上使用的这几个名称,不可以自行修改属性名。

开发持久层功能时,需要先创建接口,例如com.springboot.sample.mapper.UserMapper。此前使用传统的SSM开发时,需要在配置文件中指定接口所在的包,在SpringBoot中,可以为接口添加@Mapper注解,而无需添加配置。

@Mapper
public interface UserMapper {

}

在添加完抽象方法之后,传统的SSM开发中需要继续配置XML映射,但是,在SpringBoot的应用中,可以直接添加注解:

@Mapper
public interface UserMapper {

    @Select("select id, password from t_user where username=#{username}")
    User findByUsername(String username);

}

不难发现,当执行的任务是查询时,则添加@Select注解,与之类似的还有@Insert@Update@Delete注解,根据需要执行的任务进行选取即可!

当完成后,应该执行单元测试,可以自定义测试类,所有的测试类都应该添加注解:

@RunWith(SpringRunner.class)
@SpringBootTest
public class 测试类 ...

在编写测试方法时,所需要的对象如果是当前项目的组件,都可以自动装配:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTestCase {

    @Autowired
    private UserMapper userMapper;

    // ...其它

然后编写测试方法:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTestCase {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void findByUsername() {
        String username = "mvc";
        User user
            = userMapper.findByUsername(username);
        System.out.println(user);

        username = "hello";
        user = userMapper.findByUsername(username);
        System.out.println(user);
    }

}

至此,简单的持久层访问就已经完成!

6. 业务层(非SpringBoot知识点)

设计业务层方法时,以操作成功(操作正确)为前提来设计返回值的类型,而几乎每个业务方法都有出错的可能,出错时,直接抛出某种异常即可!

以登录为例,方法名可以使用login,符合大多数人的英语认知;返回值应该是User,因为登录成功后,可能需要将用户的id、username等数据存入Session,则使用1个User对象可以封装这多项数据;参数应该使用String username和String password,简单易懂:

User login(String username, String password);

该方法可能出现的“错误”(指的是开发者认为用户操作失败)均通过抛出异常来表现,则调用方法时的语法可能是:

try {
    User user = userService.login("", "");
    session.setAttribute(
        "id", user.getId());
    session.setAttribute(
        "username", user.getUsername());
} catch (Username异常 e) {

} catch (Password异常 e) {

}

使用这种做法,既能满足返回正确的数据,又能体现多种不同的错误,并且,在语法上表达得也非常清楚!

抛出的异常应该继承自RuntimeException,并添加父类中已经存在的多种构造方法,便于快速创建对象!通常,异常类存放在service的子级ex包中。

由于自定义的异常都是RuntimeException的子孙类异常,Java语法并不强制要求处理这些异常,则方法的调用者可能不清楚需要处理哪些异常,所以,在方法的声明中应该明确的抛出:

public User login(
    String username, String password)
        throws UserNotFoundException, 
            PasswordNotMatchException {
    // ... 
}

并且,在方法的声明中明确的添加注释:

/**
 * 用户登录
 * @param username 用户名
 * @param password 密码
 * @return 成功登录的用户数据,包括用户的id等……
 * @throws UserNotFoundException 用户数据不存在
 * @throws PasswordNotMatchException 密码不匹配
 */
public User login(
    String username, String password)
        throws UserNotFoundException, 
            PasswordNotMatchException {
    // ... ...
}

7. 控制器层

先创建com.springboot.sample.controller.UserController,添加@RestController注解,然后,添加方法处理请求:

@RestController
public class UserController extends BaseController {

    @Autowired
    private UserService userService;

    @RequestMapping("/login.do")
    public ResponseResult login(
            String username, String password) {
        User user = userService.login(
                username, password);
        return new ResponseResult(SUCCESS);
    }

}

并且,另行创建控制器的基类提供静态常量,并处理异常:

public abstract class BaseController {

    protected static final int SUCCESS = 1;

    @ExceptionHandler(ServiceException.class)
    public ResponseResult handleException(Exception e) {
        // 判断异常的种类并进行处理
        if (e instanceof UserNotFoundException) {
            return new ResponseResult(2, e);
        } else if (e instanceof PasswordNotMatchException) {
            return new ResponseResult(3, e);
        }

        return null;
    }

}