spring boot学习笔记
spring boot 是什么
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。
spring boot采用了“约定优于配置” 的理念,减少了spring繁琐的配置,方便快速搭建应用
spring boot官网:http://projects.spring.io/spring-boot/
maven配置:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
配置解读:
- 继承spring-boot-starter-parent后我们可以继承一些默认的依赖,这样就无需添加一堆相应的依赖,把依赖配置最小化
- spring-boot-starter-web提供了对web的支持,提供了嵌入式Tomcat容器以及端点信息:如服务器信息、应用指标(metrics)以及环境详情
hello world
官网中的hello-world,示例如下:
package hello; import org.springframework.boot.*; import org.springframework.boot.autoconfigure.*; import org.springframework.stereotype.*; import org.springframework.web.bind.annotation.*; @Controller // 标识是web的controller类 @EnableAutoConfiguration // 允许自动加载配置,Boot要采用一种特定的方式来对应用进行配置 public class SampleController { @RequestMapping("/") // 对应restful url的相对目录 @ResponseBody // 将返回直接作为response的body String home() { return "Hello World!"; } // 启动应用程序 public static void main(String[] args) throws Exception { SpringApplication.run(SampleController.class, args); } }
main分离
当如果有多个controller的时候,直接把main放在一个controller里面是不合适的,那么就把main单独拆分出来
UserController.class:
package sailorxiao.SpringBootSample.controller; // 约定的controller都放在controller目录下 import org.springframework.boot.*; import org.springframework.boot.autoconfigure.*; import org.springframework.stereotype.*; import org.springframework.web.bind.annotation.*; @Controller @RequestMapping("/user") @EnableAutoConfiguration public class UserController { public String helloUser() { return "Hello user!"; } } main: package sailorxiao.SpringBootSample; // 默认的main对应的class应该放在项目src代码的一级目录下,默认使用Application import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; @EnableAutoConfiguration @ComponentScan public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
如图所示,对于main函数,没法放到单独controller里面,因此:
- @EnableAutoConfiguration 标志在对应的主要class上
- @ComponentScan 允许boot依据约定的规则对项目中的bean进行扫描
增加@Autowired自动装配
通常在controller中会有一些逻辑交互,需要做一些处理(比如读写db,进行一些业务逻辑等),一般会把相关的操作放到对应的service下,如下,对UserContrller进行处理,增加UserService
UserController:
package sailorxiao.SpringBootSample.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import sailorxiao.SpringBootSample.entity.User; import sailorxiao.SpringBootSample.service.IHelloService; import sailorxiao.SpringBootSample.service.IUserService; @RestController public class UserController { @Autowired private IUserService userService; //使用了自动装备,boot会自动装配对应的service对象 @RequestMapping("/hello/{name}") // rest path中带着name,完整的url就是 http://xxxx/user/{name} public String helloUser(@PathVariable("name") String name) { return userService.helloUser(name); } }
service目录下
IUserService:
package sailorxiao.SpringBootSample.service; // 所有的service约定都放在service目录下 public interface IUserService { // 对于每个service需要定义好一个interface,直接放在service目录下,名字为IXXXService public String helloUser(String user); }
IUserServiceImpl:
package sailorxiao.SpringBootSample.service.impl; import org.springframework.stereotype.Component; import sailorxiao.SpringBootSample.service.IUserService; @Component // 需要加上这个标签,这样main的ComponentScan才能扫描到对应的实现 public class UserServiceImpl implements IUserService { @Override public String helloUser(String user) { return "hello " + user; } }
http body 约束
很多时候,会希望传入的是一些特定规则的参数,比如我们希望在UserController中传入User对象{name:xxx,age:xxx}
controller:
package sailorxiao.SpringBootSample.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import sailorxiao.SpringBootSample.entity.User; import sailorxiao.SpringBootSample.service.IUserService; @RestController public class UserController { @Autowired private IUserService userService; @RequestMapping("/hello/{name}") public String helloUser(@PathVariable("name") String name) { return userService.helloUser(name); } @RequestMapping(value = "/create", method = RequestMethod.POST) public User createUser(@RequestBody User user) { return userService.createUser(user); } }
User对象:
package sailorxiao.SpringBootSample.entity; // 一般而言与用户相关的对象都放在entity目录下 public class User { // User对象是个bean,有默认的set/get方法 private String name; private int age; public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } }
注意,在client使用json作为body传递给server的controller的时候,需要标志contentType是"application/json",如使用以下方式:
HttpClient httpClient = new HttpClient(); StringRequestEntity requestEntity = new StringRequestEntity( jsonStr, // json的序列化后的string,比如这里应该就是USER对象序列化成json的str "application/json", "UTF-8"); PostMethod postMethod = new PostMethod(url); postMethod.setRequestEntity(requestEntity); httpClient.executeMethod(postMethod); String resStr = postMethod.getResponseBodyAsString(); System.out.println("post res: " + resStr);
resource
有时候需要使用配置,那么在boot里面使用配置非常简单,如下,在定义配置后,只需要在程序中声明
application.properties: host="192.168.137.10" port=34001 properties类: @ConfigurationProperties // 声明这个是properties的bean public class BootMongoProperties { private String host; private int port; public String getHost() { return this.host; } public void setHost(String host) { this.host = host; } public int getPort() { return this.port; } public void setPort(int port) { this.port = port; } }
如果配置都是以一定名称打头的,可以加上prefix字段,如:
@ConfigurationProperties(prefix = "spring.data.mongodb") public class BootMongoProperties { private String host; //表示配置项为spring.data.mongodb.host private int port; private String uri = "mongodb://localhost/test"; // 如果配置中没有配置spring.data.mongodb.uri的话,默认为该值 public String getHost() { return this.host; } public void setHost(String host) { this.host = host; } public int getPort() { return this.port; } public void setPort(int port) { this.port = port; } }
mongodb支持
一般而言web服务中需要使用到db,那么在spring boot里面是如何进行db相关操作的呢?以mongodb为例只需要三部
第一步,配置db相关配置,如图在application.properties中配置mongodb的uri
spring.data.mongodb.uri=mongodb://sailor:sailor@192.168.137.10:34001/sailor?autoConnectRetry=true&connectTimeout=60000
spring.data.mongodb.repositories.enabled=true
第二步,声明mongoTemplate,mongodb的driver中,相关操作都是通过mongoTemplate进行的
@Resource // @Resource表示mongoTemplate直接基于配置生成对应的mongoTemplate操作实例
private MongoTemplate mongoTemplate;
第三步,使用mongoTemplate
User user = new User(name, age); // 定义一个collection相关的bean mongoTemplate.insert(user); // 从mongo中插入该数据,插入到user对应的类名的集合中(这里就是user) User类: public class User { private String name; private int age; public User() { // do nothing } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } }
通过以上三步,就能很简单得实现boot操作对应的db
问题
通过java -jar运行时,提示找不到main函数
解决方案,在pom.xml中加入mainClass选项,指明对应的mainClass
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>SailorXiao.spring.main.Main</mainClass> </configuration> </plugin> </plugins> </build>