一 基于restful风格的CRUD接口
这里相比之前有新的注解:
-
@RestController: 我们可以这样理解,@RestController = @Controller + @ResponseBody,所以使用了这个注解就是默认将数据以json形式传递给前端.
-
Apixxx: 所有关于带有Api的注解等下讲解.
-
如果接受参数的时候不使用@RequestBody注解的话,后端无法接受到前端传递过来的json数据
二 restTemplate
后端负责开发各种各样的接口,然后供给前端调用,但是偶尔会有后端需要调用后端的接口.这是什么意思呢?比如有projectA和projectB,projectA想调用projectB中的接口,这时就需要使用testTemplate.
举个例子: projectA有CRUD接口,projectB想调用projectA的CRUD接口
1. 在projectB中新建RestTemplate对象
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2. 在projectB中使用RestTemplate远程调用projectA中的CRUD接口
2.1 restTemplate.getForObject or restTemplate.getForEntity
url: projectA中对应接口的地址
getForEntity和getForObject都可以使用,getForEntity信息相对而言会多一点
2.2 restTemplate.postForObject
在使用restTemplate.postForObject相比get要多带一个参数,因为是post请求,所以要携带一个参数进去
2.3 restTemplate.deleteForObject
这里需要注意的是,delete是没有返回值的,所以不需要拿变量接受
2.4 restTemplate.exchange
2.4.1 delete
2.4.2 get
2.4.3 post
我们可以看到,exchange会更加灵活,可以适合各种请求方式,但是请注意,在post请求的时候要添加一个实体类
三 关于@Configuration和@Bean
@Configuration: 相当于创建了一个applicationContext.xml文件
@Bean注解及其方法: 相当于向SpringIOC容器注入了一个对象,id就是方法名
@Scope: 指定javaBean的作用域
四 Swagger
swagger是用来方便前后端接口文档,这个可以随时修改
1. 引入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
2. 在application.yml中添加对应配置
spring:
mvc:
pathmatch:
matching_strategy: ant_path_matcher
3.新建SwaggerConfig类,并且配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger Test App Restful API")
.description("swagger test app restful api")
.termsOfServiceUrl("https://github.com/geekxingyun")
.contact(new Contact("卡布奇诺", "https://xingyun.blog.csdn.net", "123456789@qq.com"))
.version("1.0")
.build();
}
@Bean
public Docket createRestApi(ApiInfo apiInfo) {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo)
.groupName("SwaggerGroupOneAPI")
.select()
//.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.apis(RequestHandlerSelectors.basePackage("com.cctv.controller"))
.paths(PathSelectors.any())
.build();
}
}
这里注意: 除了@Configuration和@Bean注解之外,还需要加入@EnableOpenApi注解,这里大部分代码无关紧要,最重要注意34行代码,里面有个"com.cctv.controller",这里是代表扫描到这个包
4. 关于@Apixxx讲解
@Api: 用于对类的说明
@ApiOperation: 用于对方法的说明
@ApiModelProperty: 用于对类属性的说明
Swagger访问网站: 注意自己的端口号 http://localhost:8080/swagger-ui/
4.1 相关Api注解(重点关注带有Api注解的)
4.2 Swagger显示的
五 SpringBoot整合AOP和拦截器
1. SpringBoot整合AOP
1.1 导入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1.2 定义切面类
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LogUtil {
// 前置通知
@Before("execution(* com.cctv.service..*.*(..))")
public static void before(){
System.out.println("方法前");
}
// 后置通知
@After("execution(* com.cctv.service..*.*(..))")
public static void after(){
System.out.println("方法后");
}
// 后置异常通知
@AfterThrowing("execution(* com.cctv.service..*.*(..))")
public static void afterException(){
System.out.println("方法异常");
}
// 后置返回通知
@AfterReturning("execution(* com.cctv.service..*.*(..))")
public static void afterEnd(){
System.out.println("方法返回");
}
}
这里和之前的SSM整合AOP有点类似,就不重复了
2. SpringBoot整合拦截器
2.1 创建一个类,实现HandlerInterceptor接口
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("请求处理之前进行调用(Controller方法调用之前)");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("请求处理之后进行调用,主要是在视图被渲染之前(Controller方法调用之后)");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("请求结束之后被调用,在DispatcherServlet渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
}
}
2.2 创建配置类,添加拦截器到Spring拦截器链中
import com.cctv.interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfigurator implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()). //添加拦截器
addPathPatterns("/**"). // 拦截映射规则
excludePathPatterns("/index"); // 设置排除的映射规则
/*
* 排除多个路径
* List list = new ArrayList();
list.add("/user/toIndex");
list.add("/user/loginUser");
list.add("/user/toRegister");
list.add("/user/register");
registry.addInterceptor(new UserIntercetor()).addPathPatterns("/**").excludePathPatterns(list);
*
* */
}
}
六 SpringBoot作为单体web与freemarker
如果使用了freemaker就意味着前后端会合并在一起,这里我们需要导入一个关于freemarker依赖
1. 导入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2. 在application.yml中添加配置
spring:
freemarker:
cache: false
charset: utf-8
suffix: .html
3. 可以通过${属性名}来获取值
这里注意,如果要使用freemarker的话,我们在controller层就得使用@Controller注解而不是@RestController注解,因为我们不需要返回json数据给前端. 还有就是如果使用了freemarker模板,那么我们的文件就要放到static目录下,这个就是SpringBoot中的约定大于配置
七 关于CORS跨域问题
浏览器最核心也是最基本的安全功能就是同源策略,同源既: 相同的协议,相同的主机,相同的端口. 跨域: 当一个请求url的协议,域名,端口三者任意一个与当前页面不同即为跨域.
那么SpingBoot该如何解决CORS跨域问题呢?
新建一个配置类实现WebMvcConfigurer接口并且配置
@Configuration
public class MyWebMvcConfigurator implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/user/*"); // 映射服务器中那些http接口运行跨域访问
// .allowedOrigins("http://localhost:8081") // 配置哪些来源有权限跨域
// .allowedMethods("GET","POST","DELETE","PUT"); // 配置运行跨域访问的请求方法
}
}
这样就解决了CORS跨域问题了
八 SpringBoot中的json
SpringBoot提供了与三个JSON映射库: Gson Jackson JSON-B,我们默认使用Jackson
这里介绍关于Json的几个注解
@JsonIgnore: 隐藏属性. 如果不想将某一个属性序列化,可以使用这个注解
@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss"): 用于进行日期格式化
@JsonInclude(JsonInclude.Include.NON_NULL): 如果一个属性有值的时候就序列化,没有值就不序列化
@JsonProperty: 我们的javaBean对象里面的属性名字可能和前端传递过来的属性名字不一样,那么需要可以使用这个来映射,也就是前端传递过来的是什么,这个注解里面就写个别名
九 SpringBoot和servlet整合
1. servlet容器
SpringBoot包含了对嵌入式Tomcat,Jetty和Undertow服务器的支持,默认使用Tomcat,我们也可以切换
1.1 排除Tomcat依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
1.2 导入对应的依赖
Jetty:
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
Undertow:
<dependency>
<artifactId>spring-boot-starter-undertow</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
2. listener,filter,自定义servlet
2.1 通过@WebServlet,@WebListener,@WebFilter注解
@WebServlet:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "HelloServlet", urlPatterns = "/index")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doGet(req, resp);
System.out.println("hello get");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doPost(req, resp);
System.out.println("hello post");
}
}
name: 自定义servlet的类名
urlPattern: 路由
@WebFilter:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class HelloFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException, ServletException, IOException {
System.out.println("HelloFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
}
@WebListener:
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象呗创建了。。。");
}
}
不管是哪一个,做通过@Webxxx注解之后,我们还必须在启动类中加入一个@ServletComponentScan注解
2.2 @Configuration+@Bean
import com.cctv.servlet.ContextLoaderListener;
import com.cctv.servlet.HelloFilter;
import com.cctv.servlet.HelloServlet;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyWebMvcConfiguration {
@Bean
public ServletRegistrationBean myServlet(){
// 声明一个servlet注册器Bean
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
// 设置相应的servlet
servletRegistrationBean.setServlet(new HelloServlet());
// 设置名字
servletRegistrationBean.setName("HelloServlet");
// 添加映射规则
servletRegistrationBean.addUrlMappings("/HelloServlet");
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean<HelloFilter> getFilter() {
//通过FilterRegistrationBean实例设置优先级可以生效
FilterRegistrationBean<HelloFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new HelloFilter());//注册自定义过滤器
bean.setName("flilter1");//过滤器名称
bean.addUrlPatterns("/*");//过滤所有路径
bean.setOrder(1);//优先级,最顶级
// 忽略过滤格式
bean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,");
return bean;
}
@Bean
public ServletListenerRegistrationBean getListener() {
ServletListenerRegistrationBean servletListenerRegistrationBean=new ServletListenerRegistrationBean(new ContextLoaderListener());
return servletListenerRegistrationBean;
}
}
十 将一个SpringBoot project打包成war包
众所周知,SpringBoot默认将SpringBoot project打包成jar包,但是不可避免有的时候需要将SpringBoot project打包成war包,这里就来教一教大家如何打包成war包
1. 在pom依赖文件中修改打包成war包
- 让tomcat相关的依赖不参与打包部署,因为外置tomcat服务器已经有这些jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
- 在启动类添加一个类
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class TomcatStartSpringBoot extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringbootDemoApplication.class);
}
}