spring boot: build a project from scratch - day 7 springboot devtools hot loading + MybatisPlus configuration + kisso from entry to abandonment

1. springboot devtools hot loading

Recently, I feel that it is too troublesome to restart every time the development is needed. Let’s turn this on. As for the memory consumption mentioned by my colleagues, just eat it, and the efficiency is high! ! !
(Hot loading: compile and modify the code in real time, even if there is nothing to do, it will load one by itself =. =)

1. Import configuration
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

<build>A configuration needs to be started, as follows:

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!--// fork :  如果没有该项配置,肯呢个devtools不会起作用,即应用不会restart -->
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>
2, idea placement

insert image description here
insert image description here

3. Run the project

insert image description here
The console prompts like this

insert image description here

Two, MybatisPlus configuration

I configured MybatisPlus in a hurry before, and I saw the configuration on the official website by accident today, and I feel that I am really too casual. When I switched from Mybatis to Plus, I was so impressed that this thing is so easy to use! I found that I didn't seem to be very good at matching, so I looked at the configuration. Hey, I can't quite understand the source code with my current skills.

mybatis-plus:
  configuration:
    #是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射。
    mapUnderscoreToCamelCase: true
    #MyBatis 自动映射策略,通过该配置可指定 MyBatis 是否并且如何来自动映射数据表字段与对象的属性
    autoMappingBehavior: full
    #MyBatis 自动映射时未知列或未知属性处理策略,通过该配置可指定 MyBatis 在自动映射过程中遇到未知列或者未知属性时如何处理
    autoMappingUnknownColumnBehavior: none
    #指定当结果集中值为 null 的时候是否调用映射对象的 Setter(Map 对象时为 put)方法,通常运用于有 Map.keySet() 依赖或 null 值初始化的情况。
    callSettersOnNulls: true

  global-config:
    #是否控制台 print mybatis-plus 的 LOGO  //丑拒,完全不知道意义何在
    banner: false
    #***是否初始化 SqlRunner(com.baomidou.mybatisplus.extension.toolkit.SqlRunner)
    enable-sql-runner: false
    #全局配置
    db-config:
      #全局默认主键类型
      id-type: ASSIGN_ID
      #逻辑删除字段
      logic-delete-field: removed
      #逻辑未删除值
      logic-not-delete-value: 1
      #逻辑已删除值
      logic-delete-value: 0

The enable-sql-runner configuration is false by default. Baidu saw a sentence that is quite interesting: Execute sql statements through mybatis SqlRunner, but the mybatis interceptor cannot intercept them, so the console will not print sql statements .
I followed it a little bit and looked at the source code, but I keep reporting errors, and I can’t find how to use it in the online documentation. Mark a star and be sure to do it next time.

Three, kiss


I have been thinking about how to write a single sign-on verification for the past two days. When I was studying the configuration of MybatisPlus, the mouse slid over here inadvertently. At that time, I felt that I had discovered another treasure.

kisso = cookie sso Cookie-based SSO middleware, it is a swiss army knife for rapid development of java web login system (SSO).

sure! Cookie-based means you don't need to deploy caching... right? Anyway, I used it first,
insert image description here
and then jumped to the past according to the address to think about the next case, Kang Yikang. After decompressing it N times excitedly, I found that there was no movement. I opened it and slowly typed one? ,,,? ,,,,? ? ? ? ?
insert image description here

1. The customary lead package
        <!-- kisso 登陆验证 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>kisso</artifactId>
            <version>3.7.6</version>
        </dependency>
2. Add interceptor

The official case is this

@ControllerAdvice
@Configuration
public class WebConfig extends WebServiceConfigurer {
    
    

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        // SSO 授权拦截器
        SSOSpringInterceptor ssoInterceptor = new SSOSpringInterceptor();
        ssoInterceptor.setHandlerInterceptor(new LoginHandlerInterceptor());
        registry.addInterceptor(ssoInterceptor).addPathPatterns("/**").excludePathPatterns("/v1/sso/**");
    }
}

In this case, I don't know whether the author has passed the package less or I am too good at it. WebServiceConfigurerThis parent class has been tangled for a long time, it seems that there is no such class? new LoginHandlerInterceptor()This new object is also a self-built object?
...
...
...
After calming down and thinking about it, isn't it just an interceptor? WebMvcConfigurationSupportIsn't it enough to directly inherit in spring boot ? Click on SSOSpringInterceptorthe object, the code inside is a standard interceptor structure, and you can see that a property is defined in it:

private SSOHandlerInterceptor handlerInterceptor;

Then just create a new LoginHandlerInterceptorimplementation SSOHandlerInterceptor. LoginHandlerInterceptorTwo methods are implemented in:

public class LoginHandlerInterceptor implements SSOHandlerInterceptor {
    
    
    @Override
    public boolean preTokenIsNullAjax(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
    
    
        return false;
    }

    @Override
    public boolean preTokenIsNull(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
    
    
        return false;
    }
}

In SSOHandlerInterceptorthe object, there is such a piece of code that illustrates LoginHandlerInterceptorthe functions of the two methods implemented in:

if (HttpUtil.isAjax(request)) {
    
    
    this.getHandlerInterceptor().preTokenIsNullAjax(request, response);
    return false;
}

if (this.getHandlerInterceptor().preTokenIsNull(request, response)) {
    
    
    log.debug("logout. request url:" + request.getRequestURL());
    SSOHelper.clearRedirectLogin(request, response);
}

The following are blind guesses:
1. The preTokenIsNullAjax method is the data processing return triggered when the front end uses the ajax submission
method and the obtained token is empty; 2. The preTokenIsNull method is called by the front end except using the ajax submission method and the obtained token is empty redirect to the login page;

3. Configuration instructions

This configuration can be written in the project configuration file

    /**
     * 编码格式,默认 UTF-8
     */
    private String encoding = SSOConstants.ENCODING;
    /**
     * 签名密钥(用于对此算法)
     */
    private String signKey;
    /**
     * 签名算法
     *
     * @see io.jsonwebtoken.SignatureAlgorithm
     */
    private String signAlgorithm = "HS512";
    /**
     * RSA 私钥 key.jks 存储路径
     */
    private String rsaJksStore = "key.jks";
    /**
     * RSA 公钥 public.cert 存储路径
     */
    private String rsaCertStore = "public.cert";
    /**
     * RSA 密钥 Alias
     */
    private String rsaAlias = "jwtkey";
    /**
     * RSA 密钥 keypass
     */
    private String rsaKeypass = "llTs1p68K";
    /**
     * RSA 密钥 storepass
     */
    private String rsaStorepass = "lLt66Y8L321";
    /**
     * 访问票据名
     */
    private String accessTokenName = "accessToken";
    /**
     * cookie 名称
     */
    private String cookieName = "uid";
    /**
     * cookie 所在有效域名,不设置为当前访问域名
     */
    private String cookieDomain;
    /**
     * cookie 路径
     */
    private String cookiePath = "/";
    /**
     * cookie 是否设置安全,设置 true 那么只能为 https 协议访问
     */
    private boolean cookieSecure = false;
    /**
     * cookie 是否为只读状态,设置 js 无法获取
     */
    private boolean cookieHttpOnly = true;
    /**
     * cookie 有效期 -1 关闭浏览器失效
     */
    private int cookieMaxAge = -1;
    /**
     * 是否验证 cookie 设置时浏览器信息
     */
    private boolean cookieBrowser = false;
    /**
     * 是否验证 cookie 设置时 IP 信息
     */
    private boolean cookieCheckIp = false;
    /**
     * 登录地址
     */
    private String loginUrl = "";
    /**
     * 退出地址
     */
    private String logoutUrl = "";
    /**
     * 登录成功回调地址
     */
    private String paramReturnUrl = "ReturnURL";
    /**
     * 缓存有效期设置
     */
    private int cacheExpires = CookieHelper.CLEAR_BROWSER_IS_CLOSED;
    /**
     * 访问票据
     */
    private SSOToken ssoToken;

    /**
     * 权限认证(默认 false)
     */
    private boolean permissionUri = false;

    /**
     * 插件列表
     */
    private List<SSOPlugin> pluginList;
    /**
     * SSO 缓存
     */
    private SSOCache cache;
    /**
     * SSO 权限授权
     */
    private SSOAuthorization authorization;
Fourth, write a login try
/**
     * 登录
     * @param wxUser
     * @return
     */
    @ApiOperation(value = "登陆系统", notes = "登陆系统")
    @PostMapping("/loginSys")
    @Login(action = Action.Skip)
    public Result loginSys(@RequestBody WxUser wxUser, HttpServletRequest request, HttpServletResponse response){
    
    
        // 生成 jwt 票据,访问请求头设置‘ accessToken=票据内容 ’
        String jwtToken = SSOToken.create().setId(wxUser.getAvatarUrl()).setIssuer(wxUser.getNickName()).getToken();

        //解析票据
        SSOToken ssoToken = SSOToken.parser(jwtToken);

        // Cookie 模式设置
        SSOHelper.setCookie(request, response, ssoToken);

        return Result.success(jwtToken);
    }

    /**
     * 登录
     * @param wxUser
     * @return
     */
    @ApiOperation(value = "获取用户测试", notes = "获取用户测试")
    @PostMapping("/getUserTest")
    @Login(action = Action.Normal)
    public Result getUserTest(@RequestBody WxUser wxUser, HttpServletRequest request){
    
    
        // 解析票据
        SSOToken ssoToken = SSOHelper.getSSOToken(request);

        return new Result(ssoToken);
    }

Parameters:
insert image description here
Execute first loginSysand then execute, you can see that the code can be generated getUserTest
insert image description here
by direct useSSOHelper.getSSOToken(request)

Let’s stop here today. In fact, there are still many things I want to verify. I will discuss it next time...
PS: I heard that cookies cannot be used in applets? pawn

Guess you like

Origin blog.csdn.net/qq_16253859/article/details/106343019