Spring Boot与Web开发
- RestTemplate
- MockMvc
- 在SPringBoot中使用
- SpringBoot整合swagger2
- SpringBoot的springmvc自动配置底层原理
- 包含ContentNegotiatingViewResolver和BeanNameViewResolver
- ContentNegotiatingViewResolver
- BeanNameViewResolver
- 支持提供静态资源,包括对WebJars的支持
- 支持HttpMessageConverters
- 静态index.html支持
RestTemplate
rest风格的映射请求注解常用的有:
- @RequestMapping
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
通过restTemplate调用来测试
MockMvc
MockMvc是由spring-test包提供,实现对Http请求的模拟,能够直接使用网络的形式,
转换到controller的调用,使得测试速度快、不依赖网络环境
在SPringBoot中使用
- 建立测试类
@SpringBootTest(classes = MyApplication.class)
@AutoConfigureMockMvc //专门用于做mockmvc的,由spring-test提供,依赖junit-5,如果没有该注解需要手动注入mockmvc
public class MockMvcTest {
@Autowired
MockMvc mockMvc;
/**
* 查询
* @throws Exception
*/
@Test
void testMockMvc() throws Exception {
//发起一个模拟请求,不依赖网络,不依赖web服务,不需要启动web应用
RequestBuilder builder = MockMvcRequestBuilders.get("/person/{id}", 14) //发送请求
.accept(MediaType.APPLICATION_JSON);//设置响应类型
mockMvc.perform(builder).andExpect(MockMvcResultMatchers.status().isOk()) //断言状态码为200
.andDo(MockMvcResultHandlers.print());
}
/**
* 新增
* @throws Exception
*/
@Test
void testInsertMVC() throws Exception {
String userJson = "{\n" +
" \"name\":\"诸葛亮\",\n" +
" \"age\": 25,\n" +
" \"address\": \"成都\"\n" +
"}";
RequestBuilder builder = MockMvcRequestBuilders.post("/person/add")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON) //设置请求的文本类型
.content(userJson);
mockMvc.perform(builder).andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
/**
* 删除
*/
@Test
void deleteMockMvc() throws Exception {
RequestBuilder builder = MockMvcRequestBuilders.delete("/person/{id}", 16)
.accept(MediaType.APPLICATION_JSON);
mockMvc.perform(builder).andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
}
SpringBoot整合swagger2
- 添加依赖
swagger是一系列对rest接口的描述和UI展示的规范(json),springfox整合springmvc和swagger,将代码中的注解转换为符合Swagger的规范的json文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
</parent>
<!--整合swagger2依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
- 配置文件配置
mvc:
pathmatch:
matching-strategy: ant_path_matcher
- 配置swagger配置类
@Configuration
@EnableSwagger2
public class SwaggerConfig {
//用来告诉springfox,怎么去生成swagger所需要的规范数据
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.pathMapping("/")//设置哪些接口会映射到swagger文档中
.select() //接口选择器
.apis(RequestHandlerSelectors.basePackage("com.springboot.controller")) //告诉springfox哪些接口要生成swagger文档
.paths(PathSelectors.any()) //设置哪些接口生成在swagger文档上
.build().apiInfo(new ApiInfoBuilder() //描述文档的主体信息
.title("SpringBoot整合Swagger")
.description("SpringBoot整合Swagger,详细信息.......")
.version("1.0")
.contact(new Contact("诸葛亮","","123@qq.com"))
.build()
);
}
}
添加完配置后,直接启动项目就可以了
固定访问地址:http://localhost:8080/swagger-ui.html#/
- 测试controller
@Api("用户相关操作")
@RestController
@RequestMapping("/person")
public class PersonController {
@Autowired
private PersonService personService;
/**
* 查询
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id获取用户")
public Result<Person> getPerson(@PathVariable("id") Integer id){
Person person = personService.getPersoById(id);
return new Result<>("200","查询成功",person);
}
/**
* 新增
* @return
*/
@PostMapping("/add")
@ApiOperation("添加用户")
public Result<Void> addPerson(@RequestBody Person person){
personService.insertPerson(person);
return new Result<>("200","新增成功");
}
/**
* 修改
*/
@PutMapping("/{id}")
@ApiOperation("修改用户")
public Result<Void> updatePerson(@RequestBody Person person){
personService.updatePerson(person);
return new Result<>("200","修改成功");
}
/**
* 删除
* @param id
* @return
*/
@DeleteMapping("/{id}")
@ApiOperation("根据id删除用户")
public Result<Void> deletePerson(@PathVariable("id") Integer id){
personService.deletePerson(id);
return new Result<>("200","删除成功");
}
}
SpringBoot的springmvc自动配置底层原理
SpringBoot为Spring MVC提供了自动配置,可与大多数应用程序完美配合。
自动配置在Spring的默认值之上添加了以下功能:
- 包含ContentNegotiatingViewResolver和BeanNameViewResolver
- 支持提供静态资源,包括对WebJars的支持
- 自动注册Converter,Genericveter和Fomatter Bean类
- 支持HttpMessageConverters
- 支持注册MessageCodesResolver
- 静态index.html支持
- 自动使用ConfigurationWebBindingInitializer bean
包含ContentNegotiatingViewResolver和BeanNameViewResolver
都是springmvc内置的视图解析器
ContentNegotiatingViewResolver
这个视图解析器并不会解析视图,而是委派给其他视图进行解析
所有的视图解析器,都会根据返回的视图名称进行解析,resolveViewName
@Nullable
public View resolveViewName(String viewName, Locale locale) throws Exception {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
if (requestedMediaTypes != null) {
//获得所有匹配的视图
List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
//获取最终的视图
View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
if (bestView != null) {
return bestView;
}
}
}
委派给其他视图解析器进行解析
protected void initServletContext(ServletContext servletContext) {
//从spring容器中获取所有viewResolver类型的bean
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
ViewResolver viewResolver;
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList(matchingBeans.size());
Iterator var3 = matchingBeans.iterator();
while(var3.hasNext()) {
viewResolver = (ViewResolver)var3.next();
if (this != viewResolver) {
this.viewResolvers.add(viewResolver);
}
}
由以上代码可以得出结论,它是从Spring IOC容器中获得ViewResolver类型的bean,那么我们可以自己定制一个ViewResolver,ContentNegotiatingViewResolver也会帮我们委派解析
springboot应用中目前接口都是返回json串,只有报错或者返回视图的时候才会走视图解析器。
BeanNameViewResolver
会根据handler方法返回的视图名称(test),去ioc容器中找名字叫test的一个bean,并且这个bean是view类型的 对应到具体视图并解析:
- 实例
- handler方法
@Controller
@RequestMapping("/viewtest")
public class ViewTestController {
@RequestMapping("/test")
public String test(){
return "test";
}
}
- view视图
@Component
public class Test implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter().println("测试BeanNameViewResolver");
}
}
支持提供静态资源,包括对WebJars的支持
以前要访问jpg\css、js等 这些静态资源文件,需要再web.xml中配置,在springboot中不需要配置,只需要放在约定的文件夹中(约定大于配置)
- 原理
webJars:就是将静态资源放在jar包中进行访问
比如下面对jquery的:当访问路径含有webjars(约定大于配置),就去/META-INF/resources/webjars/文件夹下(约定大于配置)去找静态资源
- 在static文件中访问的静态资源:又是什么原理呢?
会去这个字符串数组对应的文件夹去找
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
支持HttpMessageConverters
HttpMessageConverters:负责我们的http请求和响应的报文处理
静态index.html支持
在springboot中可以直接返回html视图,因为在自动配置类WebMvcAutoConfiguration配置了InternalResourceViewResolver
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}
因为InternalResourceViewResolver 被配置了,所以就可以在全局配置文件中配置:
spring:
mvc:
view:
prefix: /pages/
suffix: .html