Spring Boot 集载MyBatis与JPA

Spring Boot 集载MyBatis与JPA

什么是Spring Boot

Spring 特点

  • 能创建独立的Spring Boot应用

  • 嵌入Tomcat,Jetty Undertow而且不需要部署他们

  • 提供的“starters” poms来简化Maven配置

    https://www.cnblogs.com/qlqwjy/p/7979159.html

    Spring将很多魔法带入了Spring应用程序的开发之中,其中最重要的是以下四个核心。

    • 自动配置:针对很多Spring应用程序常见的应用功能,Spring Boot能自动提供相关配置
    • 起步依赖:告诉Spring Boot需要什么功能,它就能引入需要的库。
    • 命令行界面:这是Spring Boot的可选特性,借此你只需写代码就能完成完整的应用程序,无需传统项目构建。
    • Actuator:让你能够深入运行中的Spring Boot应用程序,一探究竟。
  • 尽可能自动配置Spring应用

  • 提供生产指标,健壮检查和外部化配置

  • 在spring boot出现之前,使用spring框架时需要大量的xml配置,现在则可以仅需要少量的配置或无需配置

    Spring优点

    Spring的目标不在于为己解决的问题领域提供新的解决方案,而是为平台带来一种新的开发体验,从而简化对这些已有技术的使用。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PjiW834j-1638550633743)(SpringBoot.assets/image-20210420104137977.png)]

Spring Boot集成第三方类库的步骤

  • 通过maven引入springboot-XXXX-starter

  • 修改yml或properties全局统一配置文件

  • 加入一个Java Config。这个属于个性化配置,如果使用通用配置,这一步不需要。

    • 官方默认集成的类库参考:
    • https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter

什么是Spring Boot Starter

Spring Boot Starter是一组被依赖第三方类库的集合

  • 如开发WEB应用,引入Spring-boot-starter-web即可,该starter会自动引入如下类库:

    • Spring ——spring核心,baens,context上下文,AOP面向切面

    • Web MVC ——Spring MVC

    • Jackson —— JSON 数据的序列化与反序列化

    • 嵌入式Servlet Container ——Tomcat

    • 日志框架Loggin——logback,slf4j

创建 Spring Boot工程

​ 自行百度

也可以直接把web环境添加进去 ——自行百度

boot 自带LOG_PATH 日志

项目结构目录

目录位置功能
src / main / java项目的java文件存放位置,初始化包包含主程序入口
XXXApplication,可以通过直接运行该类来启动Srping Boot应用
src / main / resources存放静态资源,图片、CSS、javaScript、web页面模板文件等
src / test单元测试代码目录
.gitignoregit版本管理排除文件
target 文件夹项目代码构建打包结果文件存放位置,不需要认为维护
pom.xmlmaven项目配置文件
application.properties
(application.yml)
用于存放程序各种依赖模块的配置信息,比如服务器端口,数据库连接配置等
src / main / resources / static主要用于存放CSS、图片、js等开发用到的静态文件
src / main / resources / pulic用来存放可以直接用于访问的html文件
src / main / resources / templa用于存放web开发模板文件

热加载与热部署

### devtools实现热加载
  • 依赖(创建工程时如没有勾选则加入如下依赖)

    org.springframework.boot

    spring-boot-devtools

    true

设置IDEA

  • 运行时编译配置:“shift + Ctrl + Alt + / ",选择 ”Registry“,选中打勾 compiler.automake.allow.when.app.running

代码修改后

  • 使用 Ctrl + shift + F9对修改过后的类重新编译(设置 Running Application Update Policies也可到达效果)

Controller深入

一、Controller作用

  • 处理用户请求

  • 类似于Servlet,但比Servlet更加方便灵活,自动完成了很多工作

    自动接收请求参数

    类型转换

    数据验证

二、常用注解

  1. @Controller

    将bean定义为控制器

  2. @RestController

    • RestConntroller相当于@Controller与@ResponseBody结合

      • Controller 将控制器类注入到Spring上下文环境中,该类RequestMapping标注为HTTP服务端点
      • ResponseBody的作用,请求响应默认使用的序列化方式是JSON,而不是跳转到jsp或模板页面。
  3. @RequestMapping注解

    • value: 应用请求端点,最核心的属性,用于标志请求处理方法的唯一性;
    • method: HTTP协议的method类型, 如:GET、POST、PUT、DELETE等;
    • consumes: HTTP协议请求内容的数据类型(Content-Type),如application/json, text/html;
    • produces: HTTP协议响应内容的数据类型。produces = “text/plain;charset=utf-8”
    • params: HTTP请求中必须包含某些参数值的时候,才允许被注解标注的方法处理请求。
    • headers: HTTP请求中必须包含某些指定的header值,才允许被注解标注的方法处理请求。
  4. @RequestBody与@ResponseBody

    • @RequestBody修饰请求参数,注解用于接收HTTP的body,默认是使用JSON的格式,能够使用对象或者嵌套对象接收前端数据

    • @ResponseBody修饰返回值,注解用于在HTTP的body中携带响应数据,默认是使用JSON的格式。如果不加该注解,spring响应字符串类型,是跳转到模板页面或jsp页面的开发模式。即加上这个注解开发的是一个数据接口,不加这个注解开发的是一个页面跳转控制器。
      @ResponseBody的作用其实是将java对象转为json格式的数据。当请求为PUT与DELETE时一定需要加上该注解。注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

          @GetMapping("/toIndex4")
          //加上@ResponseBody表示返回的是字符串或者json
          @ResponseBody
          public UserVo toIndex4(){
              UserVo user = new UserVo();
              user.setUid(11);
              user.setPwd("ss");
              user.setUname("许仙");
              return user;
          }
      
  5. @ModelAttribute

    @ModelAttribute主要的作用是将数据添加到模型对象中,用于视图页面显示。

  6. @PathVariable 与@RequestParam

    • @PathVariable用于URI上的{参数},如下方法用于删除一篇文章,其中id为文章id。如:我们的请求URL为“/article/1”,那么将匹配DeleteMapping并且PathVariable接收参数id=1;@PathVariable用于将请求RESTFUL风格的URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数

    • 而RequestParam用于接收普通表单方式或者ajax模拟表单提交的参数数据。

      @DeleteMapping("/article/{id}")
      public @ResponseBody AjaxResponse deleteArticle(@PathVariable Long id) 
      @PostMapping("/article")
      public @ResponseBody AjaxResponse deleteArticle(@RequestParam Long id) 
              @GetMapping("/toIndex")
      //    将它接收到的un参数名称绑定到别名uname中去
          public ModelAndView toIndex2(@RequestParam("un")String uname){
              ModelAndView mv = new ModelAndView("index");
              mv.addObject("uname",uname);
              return mv;
          }
      
  7. RequestMapping

    • @PostMapping等同于@RequestMapping的method等于POST。

    • @GetMapping等同于@RequestMapping的method等于GET。

    • @PutMapping等同于@RequestMapping的method等于PUT。

    • @DeleteMapping等同于@RequestMapping的method等于DELETE。

8.@RequestBody与@PathVariable

相当于get或者post等传过来的参数,

相当于路径上的值

/**
 * @author XuLuBao
 * @version V1.0
 * @Package com.trkj.boot1.controller
 * @date 2021/4/20 16:11
 */
@Log4j2
@RestController
//相当于这两个的作用 @Controller + @ResponseBody
public class RestFulController {
    @GetMapping("/user/{id}")
    public UserVo findUser(@PathVariable("id")int id){
        UserVo vo = new UserVo();
        vo.setUname("许仙");
        vo.setUid(1);
       log.debug("获取成功");
        return  vo;
    }
    @DeleteMapping("/user/{uid}/{na}")
    public String delUser(@PathVariable("uid")int id,@PathVariable("na")String na){
        System.out.println(id+na);
        log.debug("删除成功");
        return "成功删除!";
    }
    @PutMapping("/user")
//    对应起来
    public String alertUser( @RequestBody  UserVo vo){
        log.debug("修改成功");
        return "成功修改";
    }
    @PostMapping("/user")
    public UserVo addUser(@RequestBody UserVo vo){
        vo.setPwd("ss");
        log.debug("添加成功");
        return vo;
    }
}

三、Controller常用向客户端返回值方法

​ 1. 返回String,用于表示视图名称,如需要向客户端返回数据,可配合方法参数中的Model对象来使用。或者使用@ModelAttribute(“xx”)可直接针对参数给定别名后向Model添加对应的值。

	2. 返回String,用于表示直接向客户端返回字符串结果,此时并不是返回视图,而是直接返回数	据。该字符串可以是普通字符串,也可以Json格式字符串。需要在方法上使用```<@ResponseBody>```注解。 
	3. 返回ModelAndView,视图加数据,如需要向客户端返回数据时,用```ModelAndView```将会比较方便。

四、Controller常用传参方式

  • 普通参数

  • 参数为JavaBean对象

  • 接收Date类型的参数,默认情况下只支持yyyy/dd/mm格式的日期

  • RESTFul风格的方式参数

五、重定向

默认情况下是转发,如果是重定向,返回结果添加 redirect前缀

@RequestMapping("redirect")
public String redirect(){
	return "redirect:/hello.jsp";
}

案列

    @PostMapping("/show")
//    也会帮我封装好了,添加@ModelAttribute("user")只是往作用域里面添加了数据用于访问
    public String toShowUser(UserVo user, Model model){
        user.setPwd("15111666207");
//        相当于自动往作用域里面存放值,boot自动帮我做了这些事
//
        model.addAttribute("vo",user);
        return "show";
    }

遇到的问题

@SessionAttributes(value = {“user”},types = {User.class})

SessionAttributes 在运行之前会对参数名称为“user”的参数进行存储到session当中去

在需要对他进行清楚的的时候直接在方法中添加:SessionStatus,在方法体中调用 SessionStatus.setComplete();进行清除,但是它只能清除在SessionAttributes中存储的值

判断对象是否为空

    @GetMapping(value = "/indexU" )
    public String chkLong(User user,SessionStatus status) {
        if (user!=null&&user.getName()!=null) {
            if (user.getName().length()>=6) {
                return "index";
            }else {
                status.setComplete();
                return "login";
            }
        } else {
            status.setComplete();
            return "login";
        }
    }

在以上由于在类上添加了,得到的user是已经创建过的对象,但是它里面的值不是空,需要判断对象之后也还要判断属性。

  • List 在SessionAttributes中报错,建议使用Model进行值的存储,一直报错,拿不到值

Spring Boot 添加日志

在resources目录中添加logback-spring.xml日志文件,添加相应的日志代码

Spring Boot 整合 Swagger

添加 Maven 相关依赖,这里需要添加上WEB和SWAGGER依赖。

  • WEB依赖
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • swagger依赖,这里选择 2.9.2 版本。
<!-- swagger -->
<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>

添加配置类

  • 添加一个swagger 配置类,在工程下新建 config 包并添加一个 SwaggerConfig 配置类。

    • SwaggerConfig.java

      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.service.ApiInfo;
      import springfox.documentation.spi.DocumentationType;
      import springfox.documentation.spring.web.plugins.Docket;
      import springfox.documentation.swagger2.annotations.EnableSwagger2;
      
      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {
      
          @Bean
          public Docket createRestApi(){
              return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
                      .select()
                      .apis(RequestHandlerSelectors.any())
                      .paths(PathSelectors.any()).build();
          }
      
          private ApiInfo apiInfo(){
              return new ApiInfoBuilder()
                      .title("Kitty API Doc")
                      .description("This is a restful api document of Kitty.")
                      .version("1.0")
                      .build();
          }
      
      }
      
  • 添加一个控制类

    /**
     * @author XuLuBao
     * @version V1.0
     * @Package com.trkj.boot1test1.controller
     * @date 2021/4/21 15:12
     */
    /*方法注解*/
    @Api(value = "desc of class")
    @RestController
    public class TestController {
        /*方法注解*/
        @ApiOperation(value="desc of method",notes="notes")
        @GetMapping
        public Object hello(/*参数注解*/@ApiParam(value = "desc of param",required = true)@RequestParam String name){
            return "Hello" + name + "!";
        }
    
    }
    

Spring 跨域

  • 添加配置类

    @Configuration
    @Slf4j
    public class AppCorsConfiguration {
        private CorsConfiguration buildConfig() {
            log.debug("开始设置");
            CorsConfiguration appCorsConfiguration = new CorsConfiguration();
            appCorsConfiguration.addAllowedOrigin("http://localhost:8081");
            appCorsConfiguration.addAllowedOrigin("http://127.0.0.1:8081");
            appCorsConfiguration.addAllowedHeader("*"); // 2允许任何头
            appCorsConfiguration.addAllowedMethod("OPTIONS");
            appCorsConfiguration.addAllowedMethod("HEAD");
            appCorsConfiguration.addAllowedMethod("GET");
            appCorsConfiguration.addAllowedMethod("PUT");
            appCorsConfiguration.addAllowedMethod("POST");
            appCorsConfiguration.addAllowedMethod("DELETE");
            appCorsConfiguration.addAllowedMethod("PATCH");
            appCorsConfiguration.setAllowCredentials(true);//这两句不加不能跨域上传文件,
            appCorsConfiguration.setMaxAge(3600L);//加上去就可
            return appCorsConfiguration;
        }
    
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", buildConfig()); // 4
            return new CorsFilter(source);
        }
    }
    
    • 或者添加

      @CrossOrigin
      

Spring Boot+ JWT

什么是jwt

Json Web Token(JWT):JSON网络令牌,是为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准((RFC 7519)。JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式用于通信双方之间以 JSON 对象行使安全的传递信息。因为数字签名的存在,这些信息是可信的。

  • Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

  • JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了JWT字符串。

    + >eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
    

jwt的组成

jwt由三部分组成

  • 头部 header

    • 头部一般有两部分信息:token类型和采用的加密算法

    {

    “alg”: “HS256”,

    “typ”: “JWT”

    }

  • 载荷 plyload

    • 该部分一般存放一些有效的信息.有效信息包含了三个部分,标准中注册的声明,共有的声明,私有的声明(即自定义字段)

      注册声明是指声明名称已在IANA JSON Web Token注册表中注册并在规范中定义的声明,JWT标准中注册的声明 (建议但不强制使用) 包含七个字段:

      • iss (issuer):签发人
      • exp (expiration time):过期时间
      • sub (subject):主题
      • aud (audience):受众(接收对象)
      • nbf (Not Before):生效时间
      • iat (Issued At):签发时间
      • jti (JWT ID):编号
    • 公有声明是指未在规范中定义但已在IANA JSON Web Token注册表中注册的声明,或者使用防冲突名称命名(例如,包含命名空间)的声明。

    • 私有声明是指没有注册而是由JWT的消费者和生产者自定义的声明。正因为如此,存在名称冲突的可能性。

      {

      “sub”: “1234567890”,

      “name”: “John Doe”,

      “iat”: 1516239022

      }

  • 签证 signature

    • 签证 JWT最后一个部分.该部分是使用了HS256加密后的数据;包含了三个部分:

      • hander(base64后的)

      • payload(base64后的)

      • secret 私钥

        secret是保存在服务器端的,JWT的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,他就是你服务端的密钥,在任何场景都不应该泄露出去.一旦客户端得知了这个secret,那就意味这客户端可以自我签发JWT了.

传统Cookid+Session与JWT对比

  1. cookie+session这种模式通常是保存在内存中,而且服务从单服务到多服务会面临的session共享问题,随着用户量的增多,开销就会越大。

  2. cookie+session限制了应用的扩展能力,特别是分布式应用中各服务器如何共享session是一个非常头疼的问题。

  3. JWT只需要服务端生成token,客户端保存这个token,每次请求携带这个token,服务端认证解析就可,减轻了服务器压力。也非常适合分布式应用开发。

  4. JWT是无状态,一次性的。想修改里面的内容,就必须签发一个新的JWT。即缺陷是一旦下发,服务后台无法拒绝携带该jwt的请求(如踢除用户)

    1. 如果API设计成规范的无状态RESTful,建议使用token
    2. 如果API被不同终端消费,Cookie受限,建议使用token
    3. 如果前后端分离应用,建议使用token
    4. 如果没有使用以上方式开发,建议选择Cookie Session

JWT访问流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6W5Lp87Z-1638550633746)(SpringBoot.assets/image-20210425094857539.png)]

Spring boot JWT工程

  1. Maven依赖配置

    ​ io.jsonwebtoken

    ​ jjwt

    ​ 0.9.1

  2. application.yml配置

    jwt:
    	#密钥key
    	secret: JWTSecret
    	#HeaderKEY
    	header: JWThEADERnAME
    	#过期时间毫秒
    	expire: 100
    
    server:
      port: 8089
      #连接池配置
      servlet:
        context-path: /jwttest
    spring:
      datasource:
        url: jdbc:mysql://127.0.0.1:3308/mydb?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: root2020
        driver-class-name: com.mysql.cj.jdbc.Driver
        # 使用druid数据源
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          # 配置测试查询语句
          validationQuery: SELECT 'x'
          # 初始化大小,最小,最大
          initialSize: 10
          minIdle: 10
          maxActive: 200
          # 配置一个连接在池中最小生存的时间,单位是毫秒
          minEvictableIdleTimeMillis: 180000
          testOnBorrow: false
          testWhileIdle: true
          removeAbandoned: true
          removeAbandonedTimeout: 1800
          logAbandoned: true
          # 打开PSCache,并且指定每个连接上PSCache的大小
          poolPreparedStatements: true
          maxOpenPreparedStatements: 100
          # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
          filters: stat,wall,log4j2
          # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
          connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      redis:
        database: 0 # Redis 数据库索引(默认为 0)
        host: 127.0.0.1 # Redis 服务器地址
        port: 6379 # Redis 服务器连接端口
        password: redis2020 # Redis 服务器连接密码(默认为空)
        lettuce:
          pool:
            max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 默认 8
            max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
            max-idle: 8 # 连接池中的最大空闲连接 默认 8
            min-idle: 0 # 连接池中的最小空闲连接 默认 0
    # JWT配置
    jwt:
      # 密匙KEY
      secret: JWTSecret
      # HeaderKEY
      header: JWTHeaderName
      # Token前缀字符
      tokenPrefix: Security-c
      # 过期时间毫秒
      expire: 100000
    
    
    mybatis:
      mapper-locations: classpath:mapper/*.xml
      type-aliases-package: com.trkj.jwtdemo.entity
    
    pagehelper:
      helperDialect: mysql
      reasonable: true
      supportMethodsArguments: true
      params: count=countS
    
    
  3. 编写jwtTokenUtil工具类

    @Slf4j
    @Data
    @ConfigurationProperties(prefix = "jwt")
    @Component
    public class JwtTokenUtil {
    
        private String secret;
        private Long expire;
        private String header;
    
    
        /**
         * 生成token令牌
         *
         * @param userName 用户
         * @return 令token牌
         */
        public String generateToken(String userName) {
            Map<String, Object> claims = new HashMap<>(2);
            claims.put("sub", userName);
            //claims.put("id",user.getId());
            claims.put("created", new Date());
            return generateToken(claims);
        }
    
        /**
         * 从令牌中获取用户名
         *
         * @param token 令牌
         * @return 用户名
         */
        public String getUsernameFromToken(String token) {
            String username;
            try {
                Claims claims = getClaimsFromToken(token);
                username = claims.getSubject();
            } catch (Exception e) {
                username = null;
            }
            return username;
        }
    
        /**
         * 判断令牌是否过期
         *
         * @param token 令牌
         * @return 是否过期
         */
        public Boolean isTokenExpired(String token) {
            try {
                Claims claims = getClaimsFromToken(token);
                Date expiration = claims.getExpiration();
                log.info("in isTokenExpired date:{}",expiration.toLocaleString());
                Date date=new Date();
                log.info("in isTokenExpired now:{},exp:{} ,{}",date.toLocaleString(),expiration.toLocaleString(),expiration.before(date));
                return expiration.before(date);
            } catch (Exception e) {
                e.printStackTrace();
                return true;
            }
        }
    
        /**
         * 得到token的过期时间,测试用,可删除
         * @param token
         * @return
         */
        public Date  expirationDate(String token){
            Claims claims = getClaimsFromToken(token);
            Date expiration = claims.getExpiration();
            return expiration;
        }
    
        /**
         * 刷新令牌
         * @param token 原令牌
         * @return 新令牌
         */
        public String refreshToken(String token) {
            String refreshedToken;
            try {
                Claims claims = getClaimsFromToken(token);
                claims.put("created", new Date());
                refreshedToken = generateToken(claims);
            } catch (Exception e) {
                e.printStackTrace();
                refreshedToken = null;
            }
            return refreshedToken;
        }
    
        /**
         * 验证令牌
         *
         * @param token       令牌
         * @param userName 用户
         * @return 是否有效
         */
        public Boolean validateToken(String token, String userName) {
    
            String uname = getUsernameFromToken(token);
            return (uname.equals(userName) && !isTokenExpired(token));
        }
    
    
        /**
         * 从claims生成令牌
         * @param claims 数据声明
         * @return 令牌
         */
        private String generateToken(Map<String, Object> claims) {
            Date expirationDate = new Date(System.currentTimeMillis() + expire);
            /**
             * signWith() 签名方法。两个参数分别是签名算法和自定义的签名Key(盐)。
             * 签名key可以byte[] 、String及Key的形式传入。
             * 前两种形式均存入builder的keyBytes属性,后一种形式存入builder的key属性。
             * 如果是第二种(及String类型)的key,则将其进行base64解码获得byte[] 。
             * compact() 生成JWT
             */
            return Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setClaims(claims)
                    .setExpiration(expirationDate)
                    .setIssuedAt((Date)claims.get("created"))
                    .signWith(SignatureAlgorithm.HS512, secret)
                    .compact();
        }
    
        /**
         * 从令牌中获取数据声明
         *
         * @param token 令牌
         * @return 数据声明
         */
        private Claims getClaimsFromToken(String token) {
            Claims claims;
            try {
                claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
            } catch (Exception e) {
                claims = null;
            }
            return claims;
        }
    
    }
    
    
  4. 编写拦截器TokenInterceptor类

    @Slf4j
    @Component
    public class TokenInterceptor extends HandlerInterceptorAdapter {
    
        @Resource
        private JwtTokenUtil jwtTokenUtil;
        @Override
        public boolean preHandle(HttpServletRequest request,
                                 HttpServletResponse response,
                                 Object handler) throws SignatureException {
            /** 地址过滤 */
            String uri = request.getRequestURI() ;
            System.out.println(uri);
            if (uri.contains("/login")){
                return true ;
            }
            /** Token 验证 */
            String token = request.getHeader(jwtTokenUtil.getHeader());
            if(StringUtils.isEmpty(token)){
                token = request.getParameter(jwtTokenUtil.getHeader());
            }
            if(StringUtils.isEmpty(token)){
                throw new SignatureException(jwtTokenUtil.getHeader()+ "不能为空");
            }
            if(jwtTokenUtil.isTokenExpired(token))
                throw new SignatureException(jwtTokenUtil.getHeader() + "失效,请重新登录。");
            /** 设置 identityId 用户身份ID */
           // request.setAttribute("identityId", jwtTokenUtil.getUsernameFromToken(token));
            return true;
        }
    }
    
  5. 注册拦截器

    @Slf4j
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Resource
        private TokenInterceptor tokenInterceptor ;
        public void addInterceptors(InterceptorRegistry registry) {
            log.debug("注册TokenInterceptor");
            registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
        }
    }
    
  6. 编写控制器

    @Slf4j
    @RestController
    public class IndexController {
        @Autowired
        private JwtTokenUtil jwtTokenUtil;
        @PostMapping("/login")
        public AjaxResponse login(@RequestBody User user){
            log.info(user.toString());
            String token=jwtTokenUtil.generateToken(user.getName(),user.getId()+"");
            return AjaxResponse.success(token);
        }
        @GetMapping("/user/{id}")
        public AjaxResponse findUser(@PathVariable("id") int id){
            log.info("FindUser........................");
            User user=new User();
            user.setId(id);
            user.setName("TestName");
            user.setPwd("testPwd");
            return AjaxResponse.success(user);
        }
    }
    
  7. PostMan测试与VUE测试

文件上传

整合Mybatis

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-292RcHSC-1638550633747)(SpringBoot.assets/image-20210429142405443.png)]

依赖

基本依赖、数据库依赖、数据源依赖

	......

<dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.1.4</version>
</dependency>
<!--        分页插件-->
<dependency>
     <groupId>com.github.pagehelper</groupId>
     <artifactId>pagehelper-spring-boot-starter</artifactId>
     <version>1.2.13</version>
</dependency>
<!--        orable编码方面-->
<dependency>
      <groupId>cn.easyproject</groupId>
      <artifactId>orai18n</artifactId>
      <version>12.1.0.2.0</version>
</dependency>
<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid-spring-boot-starter</artifactId>
     <version>1.1.21</version>
</dependency>

.yml配置

server:
  port: 8088
  servlet:
    context-path: /oraclemybatis
  #连接池配置
spring:
  datasource:
    url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
    username: scott
    password: tiger
    driver-class-name: oracle.jdbc.driver.OracleDriver
      #mysql配置如下:
      #url: jdbc:mysql://127.0.0.1:3308/mydb?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
      #username: root
      #password: root2020
      #driver-class-name: com.mysql.cj.jdbc.Driver
      # 使用druid数据源
    #type: com.alibaba.druid.pool.DruidDataSource

    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 配置测试查询语句
      validationQuery: SELECT 1 FROM DUAL
      # 初始化大小,最小,最大
      initialSize: 10
      minIdle: 10
      maxActive: 200
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 180000
      testOnBorrow: false
      testWhileIdle: true
      removeAbandoned: true
      removeAbandonedTimeout: 1800
      logAbandoned: true
      # 打开PSCache,并且指定每个连接上PSCache的大小
      poolPreparedStatements: true
      maxOpenPreparedStatements: 100
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall
mybatis:
# 映射文件配置
  mapper-locations: classpath:mapper/*.xml
#  实体类的配置,主要改位置
  type-aliases-package: com.trkj.mybatisboot.entity

pagehelper:
#  指明这是oracle配置
  helperDialect: oracle
  reasonable: true
  supportMethodsArguments: true
  params: count=countS

配置druid连接池、数据源监控

  • 添加druid StatViewServlet用于展示Druid的统计信息
    • Spring boot想用使用 其它Servlet或fiter组件的功能,就必须要借用 Spring Boot 提供的 ServletRegistrationBean 接口
    • 配置Druid服务过滤器
    • 访问地址:http://localhost:8088/druid/login.html
// config 目录下
package com.trkj.oraclemybatis.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration   /*声明这是一个配置类*/
public class DataSourceConfig {
 
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")   /*读取前缀是这个的后续东西,构建出Datasource!如果没有这一步就生成的不是我们想要的东西*/
    /*不写也可以用,但是不是自己想要的,*/
    public DataSource dataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    /**
     * 配置监控服务器
     * @return 返回监控注册的servlet对象
     * @author SimpleWu
     */
    @Bean
    public ServletRegistrationBean statViewServlet() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // 添加IP白名单
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高
        //servletRegistrationBean.addInitParameter("deny", "127.0.0.1");
        // 添加控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername", "scott");
        servletRegistrationBean.addInitParameter("loginPassword", "tiger");
        // 是否能够重置数据
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    /**
     * 配置Druid服务过滤器
     * @return 返回过滤器配置对象
     */
    @Bean
    public FilterRegistrationBean statFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        // 添加过滤规则
        filterRegistrationBean.addUrlPatterns("/*");
        // 忽略过滤格式
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,");
        return filterRegistrationBean;
    }
}

创建相关page

  • dao

    • DAO必须通过@Mapper才能被Spring创建
    package com.trkj.oraclemybatis.dao;
    
    import com.trkj.oraclemybatis.entity.Dept;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface DeptDao {
        int deleteByPrimaryKey(Short deptno);
    
        int insert(Dept record);
    
        int insertSelective(Dept record);
    
        Dept selectByPrimaryKey(Short deptno);
    
        int updateByPrimaryKeySelective(Dept record);
    
        int updateByPrimaryKey(Dept record);
    }
    
  • entity

    package com.trkj.oraclemybatis.entity;
    
    import java.io.Serializable;
    import lombok.Data;
    
    /**
     * DEPT
     * @author 
     */
    @Data
    public class Dept implements Serializable {
        private Short deptno;
    
        private String dname;
    
        private String loc;
    
        private static final long serialVersionUID = 1L;
    }
    
  • service

    public interface DeptService {
        public Dept findDeptById(Short deptno);
    }
    
    @Service
    public class DeptServiceImpl implements DeptService {
        
        @Resource
        private DeptDao deptDao;
        @Override
        public Dept findDeptById(Short deptno) {
            return deptDao.selectByPrimaryKey(deptno);
        }
    }
    
    
  • controller

    @RestController
    @Slf4j
    public class DeptController {
        @Autowired
        private DeptService deptService;
        @GetMapping("/dept/{id}")
        public Dept selectFindById(@PathVariable("id") Short deptno){
            return  deptService.findDeptById(deptno);
        }
    }
    

整合JPA

导入JPA Starter依赖库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IwJwdbKW-1638550633747)(SpringBoot.assets/image-20210429162318432.png)]

<properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>cn.easyproject</groupId>
            <artifactId>orai18n</artifactId>
            <version>12.1.0.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.21</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.validation</groupId>
            <artifactId>jakarta.validation-api</artifactId>
        </dependency>
    </dependencies>

.yml

server:
  port: 8088
  #连接池配置
  servlet:
    context-path: /jpaboot
spring:
  datasource:
    url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
    username: scott
    password: tiger
    driver-class-name: oracle.jdbc.driver.OracleDriver
      #mysql配置如下:
      #url: jdbc:mysql://127.0.0.1:3308/mydb?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
      #username: root
      #password: root2020
      #driver-class-name: com.mysql.cj.jdbc.Driver
      # 使用druid数据源
    #type: com.alibaba.druid.pool.DruidDataSource

    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 配置测试查询语句
      validationQuery: SELECT 1 FROM DUAL
      # 初始化大小,最小,最大
      initialSize: 10
      minIdle: 10
      maxActive: 200
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 180000
      testOnBorrow: false
      testWhileIdle: true
      removeAbandoned: true
      removeAbandonedTimeout: 1800
      logAbandoned: true
      # 打开PSCache,并且指定每个连接上PSCache的大小
      poolPreparedStatements: true
      maxOpenPreparedStatements: 100
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall
  jpa:
    database: ORACLE
    database-platform: org.hibernate.dialect.OracleDialect
    show-sql: true
    format-sql: true
    hibernate:
      ddl-auto: update

如果是Mysql则
jpa:
database: mysql
database-platform: org.hibernate.dialect.MySQL5Dialect
show-sql: true
hibernate:
ddl-auto: update

配置druid连接池、数据源监控

定义配置类(见备注,与mybaits时一致)
添加druid StatViewServlet用于展示Druid的统计信息
Spring boot想用使用 其它Servlet或fiter组件的功能,就必须要借用 Spring Boot 提供的 ServletRegistrationBean 接口
配置Druid服务过滤器
访问地址:http://localhost:8088/druid/login.html


@Configuration
public class DataSourceConfig {
 
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    /**
     * 配置监控服务器
     * @return 返回监控注册的servlet对象
     * @author SimpleWu
     */
    @Bean
    public ServletRegistrationBean statViewServlet() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // 添加IP白名单
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高
        //servletRegistrationBean.addInitParameter("deny", "127.0.0.1");
        // 添加控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername", "root");
        servletRegistrationBean.addInitParameter("loginPassword", "root2020");
        // 是否能够重置数据
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    /**
     * 配置Druid服务过滤器
     * @return 返回过滤器配置对象
     */
    @Bean
    public FilterRegistrationBean statFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        // 添加过滤规则
        filterRegistrationBean.addUrlPatterns("/*");
        // 忽略过滤格式
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,");
        return filterRegistrationBean;
    }
}

配置JPA

  • 可单独配置jpa的配置类,无特殊要求时可直接使用yml中的配置,无需该配置类
  • 注释该类的注解,程序依旧可执行
  • 该类可用在多数据源配置

@Slf4j
@Configuration
@EnableTransactionManagement   // 开启注解事务管理,等同于xml配置文件中的 <tx:annotation-driven />
@EnableJpaRepositories(
        // 实体管理工厂引用名称,对应到@Bean注解对应的方法
        entityManagerFactoryRef="entityManagerFactory",
        //事务管理工厂引用名称,对应到@Bean注解对应的方法
        transactionManagerRef="transactionManager",
        basePackages= { "com.trkj.jpaboot.dao" }) //设置Repository所在位置
public class JpaDataConfig {
    @Resource
    @Qualifier("japDataSource")
    private DataSource japDataSource;        //primary数据源注入
    @Value("${spring.jpa.database-platform}")
    private  String primaryDialect;
    @Value("${spring.jpa.database}")
    private String dataBase;
    @Value("${spring.jpa.show-sql}")
    private String showSql;
    @Value("${spring.jpa.hibernate.ddl-auto}")
    private String ddlAuto;
    @Value("${spring.jpa.format-sql}")
    private String formatSql;

    @Bean(name = "entityManager")        //primary实体管理器
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactory(builder).getObject().createEntityManager();
    }
    @Bean(name = "entityManagerFactory")    //primary实体工厂
    public LocalContainerEntityManagerFactoryBean entityManagerFactory (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(japDataSource)
                .properties(getVendorProperties())
                .packages("com.trkj.jpaboot.entity")     //设置实体类所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }
    @Autowired
    private HibernateProperties hibernateProperties;
    @Autowired
    private JpaProperties jpaProperties;
    private Map getVendorProperties() {
        jpaProperties.getProperties().put("hibernate.show_sql",showSql);
        jpaProperties.getProperties().put("hibernate.format_sql",formatSql);
        //jpaProperties.getProperties().put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
        jpaProperties.getProperties().put("database-platform",primaryDialect);
        jpaProperties.setDatabase(Database.valueOf(dataBase));
        hibernateProperties.setDdlAuto(ddlAuto);
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),new HibernateSettings());
    }
    @Bean(name = "transactionManager")         //事务管理器
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactory(builder).getObject());
    }
}

通过JPA工具生成POJO

@Data
@Validated
public class DeptVo {
    @Max(value = 10000,message = "编号不能超过10000")
    private long deptno;
    @NotEmpty(message = "姓名不能为空")
    private String dname;
    private String loc;
}

@Entity
@Table(name = "DEPT", schema = "SCOTT", catalog = "")
public class DeptEntity {
    private long deptno;
    private String dname;
    private String loc;

    @Id
    @Column(name = "DEPTNO")
    public long getDeptno() {
        return deptno;
    }

    public void setDeptno(long deptno) {
        this.deptno = deptno;
    }

    @Basic
    @Column(name = "DNAME")
    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Basic
    @Column(name = "LOC")
    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DeptEntity that = (DeptEntity) o;
        return deptno == that.deptno &&
                Objects.equals(dname, that.dname) &&
                Objects.equals(loc, that.loc);
    }

    @Override
    public String toString() {
        return "DeptEntity{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }

    @Override
    public int hashCode() {
        return Objects.hash(deptno, dname, loc);
    }
}

定义DAO

import com.trkj.jpaboot.entity.DeptEntity;
import org.springframework.data.repository.CrudRepository;

public interface DeptDao extends CrudRepository<DeptEntity,Integer> {

}

定义Service

public interface DeptService {
    public DeptEntity addDeptEntity(DeptEntity dept);
    public DeptEntity editDept(DeptEntity dept);
    public DeptEntity findDept(DeptEntity dept);
}



@Service
@Slf4j
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptDao deptDao;


    @Transactional(transactionManager = "transactionManager")
    public DeptEntity addDeptEntity(DeptEntity dept) {
        log.info("addDeptEntity insert data..................");
        log.info(dept.toString());
        deptDao.save(dept);
        log.info("addDeptEntity insert data over..................");
        return dept;
    }


    @Override
    @Transactional(transactionManager = "transactionManager")
    public DeptEntity editDept(DeptEntity dept) {
        return this.deptDao.save(dept);
    }

    @Override
    public DeptEntity findDept(DeptEntity dept) {
        long id=dept.getDeptno();
        DeptEntity entity=this.deptDao.findById((int)id).orElse(null);
        return entity ;
    }
}

定义Controller

@RestController
@Slf4j
public class IndexController {
    @Autowired
    private DeptService deptService;
    @PostMapping("/dept")
    public AjaxResponse addDept(@RequestBody @Valid DeptVo detpVo){
        log.info("开始插入数据。。。");
        DeptEntity dept=new DeptEntity();
        BeanUtils.copyProperties(detpVo,dept);
        deptService.addDeptEntity(dept);
        AjaxResponse response=AjaxResponse.success(dept);
        return response;
    }
    @PutMapping("/dept")
    public AjaxResponse editDept(@RequestBody @Valid DeptVo detpVo){
        log.info("开始修改。。。");
        DeptEntity dept=new DeptEntity();
        BeanUtils.copyProperties(detpVo,dept);
        deptService.editDept(dept);
        AjaxResponse response=AjaxResponse.success(dept);
        return response;
    }
}

整合Mybatis与JPA

  • 同时整合JPA与MyBatis
  • 导入Maven依赖库
  • 定义数据源类(同上例)
  • 配置druid连接池(同上例)、MyBatis、jpa
  • 定义jpa相关实体\DAO\配置文件
  • 定义MyBatis相关实体\DAO\配置文件
  • 定义Service业务类
  • 定义Controller控制器

跨域配置类

@Configuration
@Slf4j
public class AppCorsConfiguration {
    private CorsConfiguration buildConfig() {
        log.debug("开始设置");
        CorsConfiguration appCorsConfiguration = new CorsConfiguration();
        appCorsConfiguration.addAllowedOrigin("http://localhost:8082");
        appCorsConfiguration.addAllowedOrigin("http://127.0.0.1:8081");
        appCorsConfiguration.addAllowedOrigin("http://localhost:8082");
        appCorsConfiguration.addAllowedOrigin("http://127.0.0.1:8082");
        appCorsConfiguration.addAllowedHeader("*"); // 2允许任何头
        appCorsConfiguration.addAllowedMethod("OPTIONS");
        appCorsConfiguration.addAllowedMethod("HEAD");
        appCorsConfiguration.addAllowedMethod("GET");
        appCorsConfiguration.addAllowedMethod("PUT");
        appCorsConfiguration.addAllowedMethod("POST");
        appCorsConfiguration.addAllowedMethod("DELETE");
        appCorsConfiguration.addAllowedMethod("PATCH");
        appCorsConfiguration.setAllowCredentials(true);//这两句不加不能跨域上传文件,
        appCorsConfiguration.setMaxAge(3600L);//加上去就可
        return appCorsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }
}

停用端口

1. >   netstat -ano|findstr 8080

2. >   >taskkill /pid 15184 /F

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RaYu41ni-1638550633748)(SpringBoot.assets/image-20210430143905011.png)]

小技巧

序列化时改变名称
//在显示的json格式时,以name显示
@JsonProperty("name")
 private String dname;

ss AppCorsConfiguration {
private CorsConfiguration buildConfig() {
log.debug(“开始设置”);
CorsConfiguration appCorsConfiguration = new CorsConfiguration();
appCorsConfiguration.addAllowedOrigin(“http://localhost:8082”);
appCorsConfiguration.addAllowedOrigin(“http://127.0.0.1:8081”);
appCorsConfiguration.addAllowedOrigin(“http://localhost:8082”);
appCorsConfiguration.addAllowedOrigin(“http://127.0.0.1:8082”);
appCorsConfiguration.addAllowedHeader("*"); // 2允许任何头
appCorsConfiguration.addAllowedMethod(“OPTIONS”);
appCorsConfiguration.addAllowedMethod(“HEAD”);
appCorsConfiguration.addAllowedMethod(“GET”);
appCorsConfiguration.addAllowedMethod(“PUT”);
appCorsConfiguration.addAllowedMethod(“POST”);
appCorsConfiguration.addAllowedMethod(“DELETE”);
appCorsConfiguration.addAllowedMethod(“PATCH”);
appCorsConfiguration.setAllowCredentials(true);//这两句不加不能跨域上传文件,
appCorsConfiguration.setMaxAge(3600L);//加上去就可
return appCorsConfiguration;
}

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", buildConfig()); // 4
    return new CorsFilter(source);
}

}


# 停用端口

```cmake
1. >   netstat -ano|findstr 8080

2. >   >taskkill /pid 15184 /F

在这里插入图片描述

小技巧

序列化时改变名称
//在显示的json格式时,以name显示
@JsonProperty("name")
 private String dname;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值