前言:本文为原创 若有错误欢迎评论!
一.Spring Boot启动
1.依赖
<groupId>(组名)</groupId>
<artifactId>(项目名)</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Demo project for Spring Boot</description>
<!--这个必须要配 不然后面所有用到springboot-starter的都会没有版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--指定编译时的jdk版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<compilerVersion>${java.version}</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
<!-- prevents endPosTable exception for maven compile -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
</plugins>
</build>
2.启动
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class);
}
}
- 不以web方式启动
- 加入的依赖是 “spring-boot-starter” 不是 “spring-boot-starter-web”
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
new SpringApplicationBuilder(Application .class)
.web(WebApplicationType.NONE)
.run(args);
}
}
二.常用注解
1.@SpringBootApplication
-
可以用作SpringBoot的启动
@SpringBootApplication=@EnableAutoConfiguration+@ComponmentScan+@Configuration*
-
注意:@ConponentScan扫描的是当前包名下的所有注入的类 所以启动类一般直接建在java代码的根目录下面
2.@RestController
- 返回的都是json数据 可以定义一个全局的Map<String,String> param
@RestController=@Controller+@responeBody
3.@RequestParam
- 对传入的url参数进行限制
@RequestParam(defaultValue=" “,name=” ")String ?
4.@RequestBody
- 接受的是model对象的json数据 必须设置请求头 content-type:application/json
@RequestBody User user
5.@RequestHeader
- 对Http的头信息 不是在参入的参数中
@RequestHeader(“access_token”) String accessToken
6.@CookieValue
- 读取http请求携带的cookie的值
@CookieValue(“cookieName”) String cookie
三.Restful协议
1.接口定义
/{city_id}/{user_id} (注意 {}里面没有引号 直接是字段名)
2.传参
//参数名和变量名不同
@PathVariable("city_id") String cityId
//参数名和变量名相同
@PathVariable String user_id
- 注意 如果参数名和字段名一致就不用给注解的括号里写东西 写的话括号里含双引号
3.返回值
- 如果是前后端不分离 返回的就是 String(页面文件路径)或者 ModelAndView
- 如果返回的数据就是json数据
- @ResponBody注解方法:返回值将转化为json数据
- 返回值为ResponseEntity<>:放回状态码即转化后的json数据
四.Http请求:
- @GetMapping:多用于查询
- @PostMapping:多用于提交表单
- @PutMapping:多用于修改
- @DeleteMapping:多用于删除
注意:前端串的参数用‘_’不要大小写结合的驼峰
五.Jackson返回结果处理:
注意:注解的是Entity的字段,为了安全性与可读性
- @JsonIgnore:在@responbody返回json数据的时候会忽略该字段 直接注解即可(如:密码)
- @JsonProperty:返回该字段时显示的是这个别名【@JsonProperty(" ")】
- @JsonFormat:把字段中的Date类型在格式化之后返回 【@JsonFormat(pattern=“yyyy-MM-dd hh:mm:ss”,locale=“zh”,timezone=“GMT+8”)】
- @JsonInclude(Include.NON_NULL):空字段不返回
六.静态资源:
1.src/main/resources下静态资源
- static: 存放静态文件,比如 css、js、image, (访问方式 http://localhost:8080/js/main.js)
- templates: 存放静态页面jsp,html,tpl
- config: 存放配置文件,application.properties
- resources: …
2.SpringBoot默认查找路径
- Spring Boot 默认会挨个从META/resources > resources > static > public 里面找是否存在相应的资源,如果有则直接返回。
3.模板引擎Thymeleaf
-
注意:如果不引人这个依赖包,html文件应该放在默认加载文件夹里面,比如resources、static、public这个几个文件夹,才可以访问*
-
依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
之后在Controller中映射路径然后直接 return " .html"(不用加路径)
4.自定义静态资源访问路径
- application.properties配置:
spring.resources.staticlocations=classpath:/METAINF/resources/,classpath:/resources/,classpath:/static/,classpath:/pu`blic/,classpath:/(src/main/resources)下的文件夹/
如果是要文件上传:
- 增加上传路径:
web.upload-path=?
- 改写路径配置:
spring.resources.staticlocations=classpath:/METAINF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/test/,file:${web.upload-path})
七.文件上传
1.MultipartFile:
- 从前端表单提交的’file’类型 在接收方法的参数直接用MultipartFile来接收
- 如果要转存可以使用‘multipartFile.transferTo()’转存
- multipartFile有其他api可以用来获取大小等
2.设置文件上传的最大值:
- 在启动类用@Bean注入配置
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
//单个文件最大
factory.setMaxFileSize("10240KB"); //KB,MB
/// 设置总上传数据总大小
factory.setMaxRequestSize("1024000KB");
return factory.createMultipartConfig();
}
八.SpringBoot打jar包
要运行jar包就必须引入该插件 否则运行后会报错:no main manifest attribute, in XXX.jar
插件:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
九.热部署
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
-
还可以设置通过version改变才执行热部署:
- 新建trigger.txt 内容:
version=1
- application.properties:
spring.devtools.restart.trigger-file=trigger.txt
十.配置文件注入
一般情况路径等信息写入.properties文件中 忌讳直接写入.java文件
- 先在静态资源中创建一个要读取的".properties"或者".yml"文件
- 给要读取配置文件的类加注解 让其可以读取配置文件:
@PropertySource({“classpath:?.properties”})
- 注意:
- 如果是application.properties配置文件就不用该注解 spring会自动读取
- 如果所有文件都是utf-8编码 但是读取配置文件还是中文乱码 那该注解加一个属性:encoding = “utf-8”
- 给要注入的变量加注解 让其读取具体的值
@Value("${ ? }")
- 如果我们想把配置文件的信息,读取并自动封装成实体类
- 给实体类注解
@ConfigurationProperties(prefix=" ")
- 然后该实体类的变量名可以直接是该配置文件前缀之后的单词 也不用在变量上再加任何注解
注意:如果prefix后面的变量和属性名相同就可以直接注入,如果不一样,就要加@value("${配置文件中变量名的全部单词}")
- 给要使用该配置实体类的类注解
@EnableConfigurationProperties({XXXProperties.class})
- 然后可以再该实体类 @Autowired 注入配置类
十一.单元测试
1.依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.使用
-
注解类:
@RunWith(“SpringRunner.class”) @SpringBootTest(classes={(启动类).class})
-
注解方法:
@Test
十二.异常处理
1.自定义异常(更加灵活)
- 定义Entity:
“extends RuntimeException”
- 调用方抛出异常:
throw new myException( , )
2.处理异常
-
注解异常捕获类:
@ControllerAdvice 或 @RestControllerAdevice
-
注解方法:
- 全局异常
@ExceptionHandler(value=Exception.class)
- 特定异常:
@ExceptionHandler(value=myException.class)
-
方法参数:
- Exception :可以获取异常信息,“e.getMessage()”
- HttpServletRequest :还可以手动添加参数HttpServletRequest 然后获得请求url “request.getRequestURL()” 并传给前端
十三.过滤器
- 过滤器和拦截器的主要区别:
- 过滤器是基于servlet的 拦截器是基于反射的
- 过滤器可以拦截所有服务器资源 拦截器只可以拦截有对应action的请求
- 过滤器不可以获得上下文 拦截器可以获得上下文
- …
1.定义一个类
@WebFilter(urlPatterns=" “,filterName=” ")
2.“implments Filter” 并重写方法
通过 “chain.doFilter”决定是否放行(不放行跳转页面:resp.sendRedirect("/?.html"))
3.在启动类加上
@ServletComponentScan
十四.监听器
1.定义一个类 并注解
@WebListener
2.在启动类加上
@ServletComponentScan
3.让刚才定义的类“implements ServletRequestListener” 或 “implements ServletContextListener”:
-
ServletRequestListener:在每个servlet(即Controller)执行的前后执行
-
ServletContextListener:在所有程序开始之前和结束之后执行 (常用于加载资源)
十五.拦截器
1.定义拦截器
- 实现:implements HandlerInterceptor
- 重写三个方法
preHandle:调用Controller某个方法之前,如果不放行
postHandle:Controller之后调用,视图渲染之前,如果控制器Controller出现了异常,则不会执行此方法response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); response.getWriter().print(" ") return false;
afterCompletion:不管有没有异常,这个afterCompletion都会被调用,用于资源清理
- 注意:拦截器中无法注入bean(即用@Autowired注入不了 被注入的对象是null)
//用WebApplicationContextUtils自己获取bean public <T> T getBean(Class<T> clazz,HttpServletRequest request){ WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); return applicationContext.getBean(clazz); }
2.定义拦截器注册类:
- 注解:@Configuration
- 实现:implements WebMvcConfigurer
- 重写:addInterceptor(InterceptorRegistry registry)
- 注册:registry.addInterceptor(new …Interceptor()).addPathPatterns(" ")
(还可以之后连续调用 “.excludePathPatterns()”) - 注册完成:WebMvcConfigurer.super.addInterceptors(registry)
3.去注册
注意:拦截路径是否有问题 ** 和 * 如果是最后路径一定要 /**, 如果是目录的话则是 /*/
十六.后置拦截器
//注意不是@Controller或者@Component
@ControllerAdvice
public class MyResponeBodyAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
//获取经过哪个controller的类返回的结果:methodParameter.getExecutable().getDeclaringClass().getName()
boolean isGraphql = StringUtils.equalsIgnoreCase(GraphQLController.class.getName(), methodParameter.getExecutable().getDeclaringClass().getName());
//获取是哪种请求方式
boolean isGet=methodParameter.hasMethodAnnotation(GetMapping.class);
if(!(isGraphql||isGet)){
//返回false就会继续往下执行 就不会执行下面的beforeBodyWrite()
return false;
}
//返回true会执行下面的beforeBodyWrite()
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
//业务逻辑....
//最后必须返回o,o指的是原来返回的对象
return o;
}
}