专栏首页转行程序员Spring Boot 从入门到实践系列教程(2)- 快速入门

Spring Boot 从入门到实践系列教程(2)- 快速入门

1.概述

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是spring boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架.

使用spring boot有什么好处

其实就是简单、快速、方便!平时如果我们需要搭建一个spring web项目的时候需要怎么做呢?

1)配置web.xml,加载spring和spring mvc

2)配置数据库连接、配置spring事务

3)配置加载配置文件的读取,开启注解

4)配置日志文件

配置完成之后部署tomcat 调试

现在非常流行微服务,如果我这个项目仅仅只是需要发送一个邮件,如果我的项目仅仅是生产一个积分;我都需要这样折腾一遍!

但是如果使用spring boot呢?

很简单,我仅仅只需要非常少的几个配置就可以迅速方便的搭建起来一套web项目或者是构建一个微服务!

2.项目构建

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath />
</parent>

最初的依赖关系非常简单:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

3.应用程序配置

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

注意我们如何使用@SpringBootApplication作为我们的主要应用程序配置类;

这相当于@Configuration@EnableAutoConfiguration@ComponentScan在一起。

最后,我们将定义一个简单的application.properties文件 - 现在只有一个属性:

server.port=8081

4.简单的MVC视图

现在让我们使用Thymeleaf添加一个简单的前端。

首先,我们需要将spring-boot-starter-thymeleaf依赖项添加到我们的pom.xml中

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-thymeleaf</artifactId> 
</dependency>

这样就可以默认启用Thymeleaf - 无需额外配置。

我们现在可以在application.properties中配置它:

spring.thymeleaf.cache=false
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
 
spring.application.name=Bootstrap Spring Boot

接下来,我们将定义一个简单的控制器和一个基本主页 - 带有欢迎消息:

@Controller
public class SimpleController {
    @Value("${spring.application.name}")
    String appName;
 
    @GetMapping("/")
    public String homePage(Model model) {
        model.addAttribute("appName", appName);
        return "home";
    }
}

home.html

<html>
<head><title>Home Page</title></head>
<body>
<h1>Hello !</h1>
<p>Welcome to <span th:text="${appName}">Our App</span></p>
</body>
</html>

注意我们如何使用我们在属性中定义的属性 - 然后注入它以便我们可以在主页上显示它。

5.安全

接下来,让我们为我们的应用程序添加安全性 - 首先包括安全启动器:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-security</artifactId> 
</dependency>

到目前为止,您希望注意到一种模式 - 大多数Spring库都可以通过使用简单的Boot starters轻松导入到我们的项目中。

一旦spring-boot-starter-security依赖于应用程序的类路径 - 默认情况下所有端点都是安全的,使用基于Spring Security内容协商策略的httpBasicformLogin

这就是为什么,如果我们在类路径上有启动器,我们通常应该通过扩展WebSecurityConfigurerAdapter类来定义我们自己的自定义安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest()
            .permitAll()
            .and().csrf().disable();
    }
}

在我们的示例中,我们允许不受限制地访问所有端点。

6.持久化

让我们从定义我们的数据模型开始 - 一个简单的Book实体

@Entity
public class Book {
  
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
 
    @Column(nullable = false, unique = true)
    private String title;
 
    @Column(nullable = false)
    private String author;
}

和它的存储库,在这里充分利用Spring Data:

public interface BookRepository extends CrudRepository<Book, Long> {
    List<Book> findByTitle(String title);
}

最后,我们当然需要配置新的持久层:

@EnableJpaRepositories("org.baeldung.persistence.repo") 
@EntityScan("org.baeldung.persistence.model")
@SpringBootApplication
public class Application {
   ...
}
  • @EnableJpaRepositories扫描指定的包以获取存储库
  • @EntityScan可以获取我们的JPA实体

为了简单起见,我们在这里使用H2内存数据库 - 这样我们在运行项目时就没有任何外部依赖关系了。

一旦我们包含H2依赖关系,Spring Boot会自动检测它并设置我们的持久性,而不需要额外的配置,除了数据源属性:

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:bootapp;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=

7.网络和控制器

接下来,让我们看一下Web层 - 我们将通过设置一个简单的控制器 - BookController来启动它。

我们将实现基本的CRUD操作,通过一些简单的验证来公开Book资源:

@RestController
@RequestMapping("/api/books")
public class BookController {
 
    @Autowired
    private BookRepository bookRepository;
 
    @GetMapping
    public Iterable findAll() {
        return bookRepository.findAll();
    }
 
    @GetMapping("/title/{bookTitle}")
    public List findByTitle(@PathVariable String bookTitle) {
        return bookRepository.findByTitle(bookTitle);
    }
 
    @GetMapping("/{id}")
    public Book findOne(@PathVariable Long id) {
        return bookRepository.findById(id)
          .orElseThrow(BookNotFoundException::new);
    }
 
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Book create(@RequestBody Book book) {
        return bookRepository.save(book);
    }
 
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        bookRepository.findById(id)
          .orElseThrow(BookNotFoundException::new);
        bookRepository.deleteById(id);
    }
 
    @PutMapping("/{id}")
    public Book updateBook(@RequestBody Book book, @PathVariable Long id) {
        if (book.getId() != id) {
          throw new BookIdMismatchException();
        }
        bookRepository.findById(id)
          .orElseThrow(BookNotFoundException::new);
        return bookRepository.save(book);
    }
}

鉴于应用程序的这一方面是一个API,我们在这里使用@ RestController注释 - 相当于@Controller@ResponseBody - 以便每个方法将返回的资源编组到HTTP响应中。

只有一个值得指出的注意事项 - 我们在这里公开我们的Book实体作为我们的外部资源。这对我们这里的简单应用程序来说很好,但在实际应用程序中,您可能希望将这两个概念分开。

8.错误处理

现在核心应用程序已准备就绪,让我们专注于使用@ControllerAdvice 的简单集中式错误处理机制:

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
 
    @ExceptionHandler({ BookNotFoundException.class })
    protected ResponseEntity<Object> handleNotFound(
      Exception ex, WebRequest request) {
        return handleExceptionInternal(ex, "Book not found", 
          new HttpHeaders(), HttpStatus.NOT_FOUND, request);
    }
 
    @ExceptionHandler({ BookIdMismatchException.class, 
      ConstraintViolationException.class, 
      DataIntegrityViolationException.class })
    public ResponseEntity<Object> handleBadRequest(
      Exception ex, WebRequest request) {
        return handleExceptionInternal(ex, ex.getLocalizedMessage(), 
          new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
    }
}

除了我们在这里处理的标准例外,我们还使用了一个自定义异常:

BookNotFoundException

public class BookNotFoundException extends RuntimeException {
 
    public BookNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
    // ...
}

这应该让您了解这种全局异常处理机制的可能性。如果您希望看到完整的实现,请查看深入的教程。

请注意,默认情况下,Spring Boot还提供/错误映射。我们可以通过创建一个简单的error.html来自定义其视图:

<html lang="en">
<head><title>Error Occurred</title></head>
<body>
    <h1>Error Occurred!</h1>    
    <b>[<span th:text="${status}">status</span>]
        <span th:text="${error}">error</span>
    </b>
    <p th:text="${message}">message</p>
</body>
</html>

与Boot中的大多数其他方面一样,我们可以使用简单的属性来控制它:

server.error.path=/error2

9.测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class }, webEnvironment 
  = WebEnvironment.DEFINED_PORT)
public class LiveTest {
 
    private static final String API_ROOT
      = "http://localhost:8081/api/books";
 
    private Book createRandomBook() {
        Book book = new Book();
        book.setTitle(randomAlphabetic(10));
        book.setAuthor(randomAlphabetic(15));
        return book;
    }
 
    private String createBookAsUri(Book book) {
        Response response = RestAssured.given()
          .contentType(MediaType.APPLICATION_JSON_VALUE)
          .body(book)
          .post(API_ROOT);
        return API_ROOT + "/" + response.jsonPath().get("id");
    }
}

10.结论

这是Spring Boot的快速而全面的介绍。

我们当然几乎没有触及表面 - 后续章节慢慢了解

本文分享自微信公众号 - 转行程序员(be_coder),作者:转行程序员

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Boot 从入门到实践系列教程(1)- 课程目录

    王炸
  • GitHub Trending被国人长期“霸榜”,国外开发者SAY NO

    近日一名国外开发者(Balazs Saros,下简称 Balazs)在个人博客发表了一篇看似是在“声讨”中国开发者的文章,标题起得有点唬人 —— "Chines...

    王炸
  • Spring Boot 从入门到实践系列教程(3)- Spring注解

    在本快速教程中,我们将探讨org.springframework.boot.autoconfigure和org.springframework.boot.aut...

    王炸
  • Spring的核心模块解析

    Spring框架是一个轻量级的集成式开发框架,可以和任何一种框架集成在一起使用,可以说是一个大的全家桶。Spring从1.x发展到现在的5.x可以说是越来越强大...

    Java技术栈
  • Swift开发: 常见问题汇总

    1、Unknown class xxClass in Interface Builder file. 这个问题出现在使用Xib时设置自定义类名的时候。在参考OC...

    梧雨北辰
  • 为什么浏览器的用户代理字符串以 Mozilla 开头?

    为什么浏览器的用户代理字符串(user-agent string)以 Mozilla 开头? ? 最早流行的浏览器是 NCSA Mosaic,它称自己为 NCS...

    程序员宝库
  • SAP最佳业务实践:SD–含客户预付款的销售订单处理(201)-3开票

    一、VA02销售订单变更(移除开票冻结) 在此活动中,移除销售订单的开票冻结。 必须手动移除开票冻结才能处理第一个预付款请求。 后勤® 销售和分销 ® 销售® ...

    SAP最佳业务实践
  • Spring Boot Admin配置详解

    兜兜毛毛
  • Linux的mktemp命令

    Linux系统有特殊的目录,专供临时文件使用。Linux使用/tmp目录来存放不需要永久保留的文件。mktemp命令专门用来创建临时文件,并且其创建的临时文件是...

    Tyan
  • 宜信容器云排错工具集

    宜信容器云是一套基于kubernetes的容器管理平台。业务线用户在容器云上部署应用程序时,常常会遇到容器无法启动或者应用程序运行不正常的情况。为了方便用户排查...

    宜信技术学院

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动