SpringBoot是基于spring框架衍生的一种新的微服务框架,如果对Spring有一定了解的同学肯定知道在Spring中需要配置各种xml文件完成bean的注册操作,随着服务越来越多,配置就变得越来越复杂,而SpringBoot就可以比较好的解决这个痛点,又例如需要搭建一个Spring MVC的环境,在maven中需要手动加入各种依赖包,但是SpringBoot却提供了spring-boot-starter-web
可以帮我们解决开发一个Java Web项目的所有依赖情况
SpringBoot不是独立于Spring存在的,SpringBoot就是把Spring的功能再次进行包装,对外暴露了更高层次的方法,使得我们在使用的时候可以省去很多配置和操作,约定俗成优于配置
,接下来就来快速学习下SpringBoot 如何使用的以及一些其他特定的功能,其中有些要稍微了解下Spring的知识,感兴趣的可以看看【目录】Spring 源码学习
项目demo地址 simple-springboot
目录
10分钟入门SpringBoot
1、Demo
2、展示所有的bean信息
3、HTTP请求 监控输出
4、Swagger
1、Demo
如下图就是SpringBoot的文件目录结构
image
Bootstrap 文件
整个的SpringBoot启动入口,如下@SpringBootApplication就是SpringBoot的自动配置相关注解,@ComponentScan则是包扫描的路径,其次包含了swagger的注解,后面再介绍
@SpringBootApplication@ComponentScan("com.demo")@EnableSwagger2public class Bootstrap { public static void main(String[] args) { SpringApplication.run(Bootstrap.class); // SpringBoot启动 } }
BeanIoc 文件
加上@Configuration就是SpringBoot的配置,里面包含的@Bean则是类似于Spring的xml文件配置的bean一致,只是从xml文件变成了类文件
// 这个参数设置的是beanIoc这个类本身bean的自定义beanName@Configuration("beanI")public class BeanIoc { @Bean public StudentService studentS1ervice() { // 在这里就是为了验证注入到spring IOC容器的名字到底是如何的,所以故意加了一个1 // 通过结束bean的刷新监听事件打印出的beanName可以具体验证该操作是否可行 return new StudentService(); } @Bean public CustomContextEventRefresh customContextEventRefresh() { return new CustomContextEventRefresh(); } @Bean public PeoplePropertiesPrefix peoplePropertiesPrefix() { return new PeoplePropertiesPrefix(); } @Bean("student") public StudentServiceWithCustomConstruct studentServiceWithCustomConstruct() { return new StudentServiceWithCustomConstruct("custom"); } @Bean("SpringContextTool") public SpringApplicationContextAware springApplicationContextAware() { // 这个bean后续会重点关注下 return new SpringApplicationContextAware(); } @Bean("bean1") public Bean1 bean1() { return new Bean1(); } }
PeoplePropertiesPrefix 文件
和properties文件做映射处理,会自动匹配符合的前缀
@ConfigurationProperties("people")public class PeoplePropertiesPrefix { private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
application.properties 文件
如上述的PeoplePropertiesPrefix的注解信息是people开头,则会自动和下面的people开头的属性进行映射处理
people.name=zhangsan people.age=18 people=hello
StudentController 文件
该文件中列举了在HTTP请求中不同的参数提交方式,并且所有的方法都加上了@ResponseBody,则意味着直接以函数的返回值为HTTP请求的body数据填充。
无参数的GET请求方式
带?参数的GET请求方式
带路径参数的GET请求方式
JSON参数的POST请求方式
Map参数的POST请求方式
表单提交的POST请求方式
其次关于swagger以及获取bean信息的相关点后面再介绍
@RequestMapping("/")@Controllerpublic class StudentController { @Resource private StudentService studentService; @Resource private PeoplePropertiesPrefix peoplePropertiesPrefix; @Resource private SpringApplicationContextAware springApplicationContextAware; @Value("${people}") protected String people; @ApiOperation("基础GET请求") @GetMapping("/index") @ResponseBody public String index() { // 非常基础的get请求 return "{\"name\":\"zhangsan\"}"; } @ApiOperation("基础POST请求") @PostMapping("/index.do") @ResponseBody public String indexPost(@RequestBody Student student) { // 使用json的方式去提交 String name = student.getName(); return "{\"name\":\"" + name + "\"}"; } @ApiOperation("带路径参数的GET请求") @GetMapping("/index2/{id}") @ResponseBody public String indexGet(@PathVariable String id) { // get的方式,带上了路径参数 return "{\"id\":\"" + id + "\"}"; } @ApiOperation("带上?参数的GET请求") @GetMapping("/index3/") @ResponseBody public String indexGetWithPar(@RequestParam String id, @RequestParam int age) { // get的方式,带上get请求的参数 Map<String, Object> map = new HashMap<>(2); map.put("id", id); map.put("age", age); return JSON.toJSONString(map); } @ApiOperation("Map参数的POST请求") @PostMapping("/indexPost") @ResponseBody public String indexPost2(@RequestBody Map map) { return "{\"id\":\"" + map.get("id") + "\"}"; } @ApiOperation("Form参数的POST请求") @RequestMapping(value = "/indexPostForm", method = RequestMethod.POST) @ResponseBody public String indexPost3(Student student) { // 其实content-type是application/x-www-form-urlencoded String name = student.getName(); return "{\"name\":\"" + name + "\"}"; } @PostMapping("indexb1") @ResponseBody public String indexBean1(Student student) { Map<String, Object> map = new HashMap<>(2); map.put("id", studentService.getName(student)); map.put("age", studentService.getAge(student)); return JSON.toJSONString(map); } @GetMapping("/indexp") @ResponseBody public String indexp() { // 非常基础的get请求 Map<String, Object> map = new HashMap<>(2); map.put("name", peoplePropertiesPrefix.getName()); map.put("age", peoplePropertiesPrefix.getAge()); map.put("all", people); return JSON.toJSONString(map); } @ApiOperation(value = "获取Spring Bean信息", notes = "Spring Bean") @GetMapping("/indexbc") @ResponseBody public String indexBeanCount() { // 非常基础的get请求,获取bean的信息 // 后面再介绍这个请求 List<String> list = new ArrayList<>(); for(String beanName: springApplicationContextAware.getBeanName()){ list.add(beanName + "\n"); } return JSON.toJSONString(list); } @PostMapping("/get_request_info") @ResponseBody public String indexWithHeader(HttpServletRequest request, @RequestBody Map map) { Enumeration<String> headers = request.getHeaderNames(); Map<String, Object> res = new HashMap<>(2); res.put("requestBody", map); Map<String, Object> requestHeader = new HashMap<>(10); res.put("requestHeader", requestHeader); while (headers.hasMoreElements()) { String header = headers.nextElement(); String value = request.getHeader(header); requestHeader.put(header, value); } System.out.println(JSON.toJSONString(res)); return JSON.toJSONString(res); } }
POM 文件
核心的POM文件
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> </parent> <properties> <java_source_version>1.8</java_source_version> <java.version>1.8</java.version> <java_target_version>1.8</java_target_version> <file_encoding>UTF-8</file_encoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 和AOP 有关 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency> <!--json--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.40</version> </dependency> </dependencies>
好了,到现在整个的SpringBoot 项目算是完成了,默认了HTTP端口是8080,运行Bootstrap的main方法启动项目,直到最后输出如下日志信息
image
利用postman工具能够很方便的测试我们的项目是否运行正常
image
image
到这里整个的SpringBoot的demo就完成了
2、展示所有的bean信息
现在提一个问题,我们该如何获取到Spring IOC容器所有的bean信息然后输出到网页上?
想要解决这个问题,那第一点肯定要获取到Spring IOC容器的上下文,然后从上下文中获取bean信息,这个可以由ApplicationContextAware接口的实现类完成,他有一个set方法,可以注入上下文信息,然后获取该实现类间接获取到所有的bean信息就可以了。
SpringApplicationContextAware 文件
public class SpringApplicationContextAware implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 通过这种形式就获取到了Spring 本身的上下文内容了 // 该方法由spring在aware操作时调用,此时对象本身已经实例化了 SpringApplicationContextAware.applicationContext = applicationContext; } public int getBeanCount() { // 获取了上下文之后,调用其方法获取bean的个数 return applicationContext.getBeanDefinitionCount(); } public String[] getBeanName() { return applicationContext.getBeanDefinitionNames(); } }
然后通过@Bean的形式,注入了SpringContextTool的bean对象,紧接着直接调用getBeanName方法,直接输出即可,如下图就是输出的bean所有的信息
image
其实在demo中还有个使用
3、HTTP请求 监控输出
这个其实是使用了Spring MVC 的publishEvents参数(默认为true),然后利用ServletRequestHandledEvent事件完成,具体可看如下的FrameworkServlet类文件
private void publishRequestHandledEvent( HttpServletRequest request, HttpServletResponse response, long startTime, Throwable failureCause) { if (this.publishEvents) { // 默认为true long processingTime = System.currentTimeMillis() - startTime; int statusCode = (responseGetStatusAvailable ? response.getStatus() : -1); this.webApplicationContext.publishEvent( new ServletRequestHandledEvent(this, request.getRequestURI(), request.getRemoteAddr(), request.getMethod(), getServletConfig().getServletName(), WebUtils.getSessionId(request), getUsernameForRequest(request), processingTime, failureCause, statusCode)); } }
现在我们只需要设置好ServletRequestHandledEvent的事件监听器就行
public class CustomServletRequestHandledEventRefresh implements ApplicationListener<ServletRequestHandledEvent> { @Override public void onApplicationEvent(ServletRequestHandledEvent event) { FrameworkServlet frameworkServlet = (FrameworkServlet)event.getSource(); String clientAddress = event.getClientAddress(); String desc = event.getDescription(); String methodName = event.getMethod(); String requestUrl = event.getRequestUrl(); String servletName = event.getServletName(); int statusCode = event.getStatusCode(); long time = event.getTimestamp(); System.out.println(JSON.toJSONString(event)); // 打印在控制台上 } }
然后注册该bean即可,他是实现ApplicationListener接口的,处理为HTTP请求后由Spring框架自身调用完成,输出的结果如下图,还可以设置异步的线程池异步处理该事件,更多的可以看看
image
4、Swagger
swagger是一个第三方的工具,更多可参考Swagger 官网,这里我们忽略其编辑器的功能,关注其界面化的展示最新的API接口文档并可以进行调用测试的功能。
POM设置
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version></dependency>
Swagger Bean 设置
@Bean("swaggerDocker")public Docket docket() { ApiInfo apiInfo = new ApiInfoBuilder() .title("Spring Boot Swagger DEMO") .description("学习swagger") .version("1.0") .build(); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo) .select() .apis(RequestHandlerSelectors.basePackage("com.demo")) // API 扫描的包路径,一般建议是controller一层即可 .paths(PathSelectors.any()) .build(); }
Controller 设置
目前只介绍ApiOperation,其实还有不少参数,更多自行查看官网文档
@ApiOperation(value = "获取Spring Bean信息", notes = "Spring Bean")// 设置函数的标题,以及其描述信息
最后在Bootstrap文件加上@EnableSwagger2
就完成了整个的Swagger 工具接入,输入http://127.0.0.1:8080/swagger-ui.html#/student-controller,可以看到如下图的接口文档
image
image
到此整个的SpringBoot的入门使用就完成了。
作者:jwfy
链接:https://www.jianshu.com/p/a4101ff4df82