美文网首页
Spring boot 入门(技术分享)

Spring boot 入门(技术分享)

作者: mxl0814 | 来源:发表于2019-03-21 09:10 被阅读0次

    构建一个Spring Boot应用

    先决条件
    • Java开发神器IDEA
    • JDK 1.8或更高版本
    • Maven 3.2+ 或者 Gradle 4+

    通过Maven来构建

    如果您不还熟悉maven,请参阅 使用Maven构建Java项目

    接下来,我们通过IDEA 来快速创建maven项目。

    1. 点击New->Project...
    1. 选择Maven,点击Next
    1. 输入GroupIdArtifactIdVersion,点击 Next
    1. 输入Project nameProject location,点击 Finish
    1. 项目创建成功后,你会得到如下界面

    添加classpath依赖项

    pom.xml描述了用于构建项目的策略,为了使得我们的项目支持spring-boot,我们需要在pom.xml添加如下依赖:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.sunmi</groupId>
        <artifactId>sping-boot-study</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <!--父节点启动器-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.3.RELEASE</version>
        </parent>
    
        <dependencies>
            <!--spring-boot依赖项-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    
    </project>
    

    Spring Boot提供了许多“Starters”,可以将jar添加到classpath中。 我们的示例应用程序已经在pom.xml文件中指定parentspring-boot-starter-parentspring-boot-starter-parent是一个特殊的启动器,提供有用的maven默认值。 它还提供了一个依赖项的version,以便您可以省略依赖项的版本标记。


    创建一个Application

    在这里,您将使用组件创建一个应用程序类:
    src/main/java/hello/Application.java

    package hello;
    
    import java.util.Arrays;
    
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
        @Bean
        public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
            return args -> {
    
                System.out.println("Let's inspect the beans provided by Spring Boot:");
    
                String[] beanNames = ctx.getBeanDefinitionNames();
                Arrays.sort(beanNames);
                for (String beanName : beanNames) {
                    System.out.println(beanName);
                }
    
            };
        }
    
    }
    
    @SpringBootApplication是一个便利注释,添加了以下所有内容:
    • @Configuration 标记该类作为应用程序上下文的bean定义的来源。
    • @EnableAutoConfiguration 告诉Spring Boot开始根据classpath设置,其他bean和各种属性设置添加bean
    • 通常你会为Spring MVC应用添加@EnableWebMvc 注解,但Spring Boot会在classpath上看到webmvc时自动添加它。 这会将应用程序标记为Web应用程序,并激活关键行为以及设置调度程序servlet
      这会将应用程序标记为Web应用程序,并在安装DispatcherServlet时激活关键行为。
    • @ComponentScan 告诉Springhello包中寻找其他componentsconfigurationsservices

    main()方法使用Spring BootSpringApplication.run()方法来启动应用程序。 您是否注意到没有一行XML? 也没有web.xml文件。 此Web应用程序是100%Java,您无需处理配置任何管道或基础结构。

    还有一个标记为@BeanCommandLineRunner方法,它在spring boot启动时运行。 示例中它将检索由您的应用程序创建或Spring Boot自动添加的所有bean。 它对它们进行分类并打印出来。


    运行该应用程序

    mvn spring-boot:run


    创建一个简单的Web应用程序

    现在,我们为简单的Web应用程序创建Web controller:
    src/main/java/hello/HelloController.java

    package hello;
    
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @RestController
    public class HelloController {
    
        @RequestMapping("/")
        public String index() {
            return "Greetings from Spring Boot!";
        }
    
    }
    

    该类被标记为@RestController,这意味着Spring MVC可以使用它来处理Web请求。 @RequestMapping/映射到index()方法。 从浏览器访问或在命令行上使用curl时,该方法返回纯文本。 这是因为@RestController结合了@Controller@ResponseBody,两个注释导致Web请求返回数据而不是视图。


    检查服务
    1. 第一个终端执行mvn spring-boot:run
    2. 第二个终端执行
    $ curl localhost:8080
    Greetings from Spring Boot!
    

    添加单元测试

    您将需要为endpoint添加测试,Spring Test已经为此提供了一些机制,并且很容易包含在您的项目中。

    maven中加入如下依赖

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

    现在编写一个简单的单元测试,通过endpoint模拟servlet请求和响应:

    package hello;
    
    import static org.hamcrest.Matchers.equalTo;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    public class HelloControllerTest {
    
        @Autowired
        private MockMvc mvc;
    
        @Test
        public void getHello() throws Exception {
            mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
        }
    }
    

    MockMvc对象来自Spring Test,它允许您通过一组便利构造器类将HTTP请求发送到DispatcherServlet并对结果进行断言。 请注意@AutoConfigureMockMvc@SpringBootTest一起使用以注入MockMvc实例。 使用@SpringBootTest后,web应用程序会被自动创建。

    除了模拟HTTP请求周期之外,我们还可以使用Spring Boot编写一个非常简单的全栈集成测试。 例如,我们可以这样做,而不是上面的模拟测试:

    package hello;
    
    import static org.hamcrest.Matchers.*;
    import static org.junit.Assert.*;
    
    import java.net.URL;
    
    import org.junit.Before;
    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.boot.test.web.client.TestRestTemplate;
    import org.springframework.boot.web.server.LocalServerPort;
    import org.springframework.http.ResponseEntity;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class HelloControllerIT {
    
        @LocalServerPort
        private int port;
    
        private URL base;
    
        @Autowired
        private TestRestTemplate template;
    
        @Before
        public void setUp() throws Exception {
            this.base = new URL("http://localhost:" + port + "/");
        }
    
        @Test
        public void getHello() throws Exception {
            ResponseEntity<String> response = template.getForEntity(base.toString(),
                    String.class);
            assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
        }
    }
    

    嵌入式服务器通过webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT在随机端口上启动,并在运行时使用@LocalServerPort发现实际端口。


    创建一个可执行的Jar

    我们通过创建一个包含全部依赖的可执行jar文件来完成我们的示例,我们可以在生产中运行它。 可执行jar(有时称为“fat jar”)是包含已被编译的代码以及需要的全部依赖jar的归档。

    要创建可执行jar,我们需要将spring-boot-maven-plugin添加到我们的pom.xml中。 为此,请在依赖项部分下方插入以下行:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    

    接着在终端执行如下命令

    mvn package

    查看target目录,则应该看到sping-boot-study-1.0-SNAPSHOT.jar。 该文件大小应为10 MB左右。 如果你想查看jar的内部,你可以使用jar tvf,如下所示:

    jar tvf target/sping-boot-study-1.0-SNAPSHOT.jar

    要运行该应用程序,请使用java -jar命令,如下所示:

    java -jar target/sping-boot-study-1.0-SNAPSHOT.jar

    和以前一样,要退出应用程序,请按ctrl-c


    Spring-boot使用MySQL访问数据


    创建数据库

    打开终端,例如在Linux/Mac 上,我们使用命令

    $ sudo mysql --password
    

    这以管理员身份连接到MySQLbash

    1. 创建一个新的数据库
    mysql> create database db_example; -- 创建新的数据库
    mysql> create user 'springuser'@'localhost' identified by 'ThePassword'; -- 创建一个用户
    mysql> grant all on db_example.* to 'springuser'@'localhost'; -- 对新创建的数据库的所有权限给予新创建的用户
    
    1. 查看创建的数据库
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | db_example         |
    | mydatabase         |
    | mysql              |
    | performance_schema |
    | sys                |
    +--------------------+
    6 rows in set (0.00 sec)
    
    1. 查看新创建的user
    mysql> SELECT User FROM mysql.user;
    +---------------+
    | User          |
    +---------------+
    | springuser    |
    | mysql.session |
    | mysql.sys     |
    | root          |
    +---------------+
    4 rows in set (0.00 sec)
    

    配置spring-boot
    1. 修改src/main/resources/application.yml文件
    spring:
      jpa:
        hibernate:
          ddl-auto: update
      datasource:
        url: jdbc:mysql://localhost:3306/db_example
        username: springuser
        password: ThePassword
    

    spring.jpa.hibernate.ddl-auto可以是noneupdatecreatecreate-drop,有关详细信息,请参阅Hibernate文档

    • none: 这是MySQL的默认值,不会更改数据表结构。
    • update: Hibernate根据给定的实体结构更改数据表结构。
    • create 每次创建数据表,但在关闭时不会删除数据表。
    • create-drop 创建数据表,然后在SessionFactory关闭时删除它。

    我们这里以create开头,因为我们还没有数据表结构。 第一次运行后,我们可以根据程序要求将其切换为updatenone。 如果要对数据表结构进行一些更改,请使用update

    在数据库处于生产状态后,您可以使用none并从连接到Spring应用程序的MySQL用户撤消所有权限,然后只给他SELECTUPDATEINSERTDELETE,这是一种很好的安全做法。
    本指南最后详细介绍了这一点。

    1. pom.xml添加如下依赖
            <!--提供了spring boot java持久化API-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
    
            <!--提供了操作mysql的依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    

    创建 @Entity 模型

    src/main/java/hello/User.java

    package com.sunmi.bean;
    
    import lombok.Data;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    
    @Entity // 这告诉Hibernate从这个类中创建一个表
    @Data //省去get、set 等方法的编写
    public class User {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Integer id;
    
        private String name;
    
        private String email;
    
    }
    

    Hibernate将把带有@Entity注解的实体类自动转换为数据库表的结构。


    创建操作数据表的接口
    package com.sunmi.repository;
    
    import com.sunmi.bean.User;
    import org.springframework.data.repository.CrudRepository;
    
    public interface UserRepository extends CrudRepository<User, Integer> {
    }
    

    spring将会自动创建一个实现了 UserRepository 接口的 bean,包括CRUD等接口。

    创建控制器
    package com.sunmi.controller;
    
    import com.sunmi.bean.User;
    import com.sunmi.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping(path = "/demo") // 这意味着访问url以/demo开始
    public class MainController {
    
        //这意味着spring会自动生成userRepository bean对象并注入,我们用这个对象来和mysql交互
        @Autowired
        private UserRepository userRepository;
    
    
        @PostMapping(path = "/add")
        public String addNewUser(@RequestBody User user) {
            userRepository.save(user);
            return "Saved";
        }
    
        @GetMapping(path = "/add2")
        public String addNewUser(String name
                , @RequestParam String email) {
            User user = new User();
            user.setName(name);
            user.setEmail(email);
            userRepository.save(user);
            return "Saved2";
        }
    
    
    
        @GetMapping(path = "/all")
        public Iterable<User> getAllUsers() {
            // 返回所有的用户
            return userRepository.findAll();
        }
    
        @GetMapping(path = "/delete")
        public String delete(@RequestParam Integer id) {
            userRepository.deleteById(id);
            return "ok";
        }
    
        @GetMapping(path = "/find-by-id")
        public Optional<User> find(@RequestParam Integer id) {
            return userRepository.findById(id);
        }
    
    }
    

    上面的示例没有明确指定GETPUTPOST等,因为@GetMapping@RequestMapping(method = GET)的快捷方式。 @RequestMapping默认映射所有HTTP操作。 使用@RequestMapping(method = GET)或其他快捷方式注解来限制映射。


    测试我们的服务
    1. 添加一个user对象
    $ curl 'http://localhost:8080/demo/add2?name=First&email=someemail@someemailprovider.com'
    

    响应应该如下

    Saved
    
    1. 查询所有的user
    $ curl 'http://localhost:8080/demo/all'
    

    响应应该如下

    [{"id":1,"name":"First","email":"someemail@someemailprovider.com"}]
    
    1. 更新用户通过id
    $ curl --request POST --header "Content-Type: application/json" http://localhost:8080/demo/add --data '{"id":1,"name":"Test","email":"someemail@someemailprovider.com"}'
    Saved
    
    1. 查询用户通过id
    $ curl 'http://localhost:8080/demo/find-by-id?id=1'
    {"id":1,"name":"Test","email":"someemail@someemailprovider.com"}
    
    1. 删除用户通过id
    $ curl 'http://localhost:8080/demo/delete?id=1'
    "ok"
    $ curl 'http://localhost:8080/demo/find-by-id?id=1'
    null
    
    1. 你可能注意到对于add2接口,其第二个参数带有@RequestParam注解,这表明来自客户端的请求必须包含该字段。
    $ curl 'http://localhost:8080/demo/add2?name=First'
    

    你将得到如下错误

    {"timestamp":"2019-03-22T04:49:29.239+0000","status":400,"error":"Bad Request","message":"Required String parameter 'email' is not present","path":"/demo/add2"}>
    

    如果只指定了email字段

    $ curl 'http://localhost:8080/demo/add2?email=someemail@someemailprovider.com'
    Saved
    $ curl 'http://localhost:8080/demo/all'
    [{"id":1,"name":"First","email":"someemail@someemailprovider.com"}, 
    {"id":2,"name":null,"email":"someemail@someemailprovider.com"}]
    
    1. 简化服务端的编码

    当一个接口的参数过多时,我们可以通过@RequestBody注解,将这些参数组合成一个bean对象,客户端访问只需要传递一个json对象(其中的字段是可选的),服务端接收到请求后会自动将json对象系列化为bean

    访问此接口,并传递json对象

    $ curl --request POST --header "Content-Type: application/json" http://localhost:8080/demo/add --data '{"name":"Second","email":"someemail@someemailprovider.com"}'
    Saved
    
    $ curl 'http://localhost:8080/demo/all'
    [{"id":1,"name":"First","email":"someemail@someemailprovider.com"}, 
    {"id":2,"name":null,"email":"someemail@someemailprovider.com"},
    {"id":3,"name":Second,"email":"someemail@someemailprovider.com"}]
    
    进行一些安全性更改

    现在,当您处于生产环境中时,可能会遇到SQL注入攻击。 黑客可能会注入DROP TABLE或任何其他破坏性SQL命令。 因此,作为安全实践,在将应用程序公开给用户之前,请对数据库进行更改。

    mysql> revoke all on db_example.* from 'springuser'@'localhost';
    

    这将撤消与Spring应用程序关联的用户的所有权限。 现在Spring应用程序无法在数据库中执行任何操作。 我们不希望如此。

    mysql> grant select, insert, delete, update on db_example.* to 'springuser'@'localhost';
    

    这为Spring应用程序提供了仅更改数据库数据而不是数据表结构所需的权限。
    并修改src/main/resources/application.yml文件

    spring.jpa.hibernate.ddl-auto=none
    

    而不是第一次运行时用的create

    如果要对数据库进行更改,请重新授予权限,将spring.jpa.hibernate.ddl-auto更改为update,然后重新运行应用程序,然后再重新授予权限,并将spring.jpa.hibernate.ddl-auto改为none。 或者,更好的是,使用专用的迁移工具,如FlywayLiquibase


    响应式的方式访问 Redis数据

    待更新...

    参考文档
    https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started-first-application.html
    https://spring.io/guides/gs/spring-boot/#scratch
    https://spring.io/guides/gs/accessing-data-mysql/
    https://www.linuxprobe.com/mysql-show-all-users.html
    https://blog.csdn.net/mccand1234/article/details/53456411
    https://stackoverflow.com/questions/7172784/how-to-post-json-data-with-curl-from-terminal-commandline-to-test-spring-rest
    https://github.com/spring-guides/gs-accessing-data-mysql/blob/master/complete/pom.xml


    更多spring-boot技术资料
    `

    相关文章

      网友评论

          本文标题:Spring boot 入门(技术分享)

          本文链接:https://www.haomeiwen.com/subject/mmlgmqtx.html