1. 程式人生 > 其它 >springboot-WebMvcConfigurer(攔截器、跨域訪問、格式化、註冊Controller)

springboot-WebMvcConfigurer(攔截器、跨域訪問、格式化、註冊Controller)

WebMvcConfigurer是用來全域性定製化Spring Boot的MVC特性。開發者通過實現WebMvcConfigurer介面來配置應用的MVC全域性特性。

package com.gcz.conf.mvc;

import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.*;

/**
 * @author guocz
 * @date 20210621
 * MVC全域性特性
 */
public class MvcConfigurer implements
WebMvcConfigurer { /** * 攔截器 * @param registry 註冊 */ @Override public void addInterceptors(InterceptorRegistry registry){ } /** * 跨域訪問配置 * @param registry 註冊 */ @Override public void addCorsMappings(CorsRegistry registry){ }
/** * 格式化 * @param registry 註冊 */ @Override public void addFormatters(FormatterRegistry registry) { } /** * URI到檢視的對映 * @param registry 註冊 */ @Override public void addViewControllers(ViewControllerRegistry registry){ }
// 其他更多全域性定製介面 }

攔截器

通過addInterceptors方法可以設定多個攔截器,比如對特定的URI設定攔截器以檢查使用者是否登入,列印處理使用者請求耗費的時間等。

例:

1、全域性定製攔截器:

package com.gcz.conf.interceptor;

import com.gcz.conf.interceptor.handler.SessionHandlerInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author guocz
 * @date 20210621
 * 全域性攔截器
 */
@Configuration
public class MvcInterceptor implements WebMvcConfigurer {

    /**
     * 攔截器
     * @param registry 註冊
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(new SessionHandlerInterceptor()).addPathPatterns("/admin/**");
    }
}

2、會話處理類SessionHandlerInterceptor

package com.gcz.conf.interceptor.handler;

import cn.hutool.core.util.StrUtil;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author guocz
 * @date 20210621
 * 會話處理攔截器
 */
public class SessionHandlerInterceptor implements HandlerInterceptor {

    private final static String TOKEN = "12345";

    /**
     * Controller處理前
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @param handler 處理物件
     * @return true or false
     * @throws Exception 異常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Controller處理前");
        String token =request.getParameter("token");
        if (!StrUtil.equals(token, TOKEN)) {
            // 如果沒登入,重定向到login.html
            response.getWriter().write("FAIL,PLEASE SIGN IN !");
            response.setStatus(400);
            response.getWriter().close();
            return false;
        }
        return true;
    }

    /**
     * Controller方法處理完畢後,呼叫此方法
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @param handler 處理物件
     * @param modelAndView 檢視
     * @throws Exception 異常
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("Controller方法處理完畢後,呼叫此方法");
    }

    /**
     * 頁面渲染完畢後呼叫此方法,通常用來清除某些資源,類似Java語法的finally
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @param handler 處理物件
     * @param ex 異常
     * @throws Exception 異常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("頁面渲染完畢後呼叫此方法,通常用來清除某些資源,類似Java語法的finally");
    }

}

3、相關呼叫測試

package com.gcz.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author guocz
 * @date 20210621
 * 使用者
 */
@Controller
@RequestMapping("/admin")
public class UserController {

    @ResponseBody
    @RequestMapping("/getUser.json")
    public void getUser(HttpServletResponse response) throws IOException {
        response.getWriter().write("ON LINE");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().close();
    }

    @ResponseBody
    @RequestMapping("/checkUser.json")
    public void checkUser(HttpServletResponse response) throws IOException {
        response.getWriter().write("SUCCESS");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().close();
    }
}

跨域訪問

出於安全的考慮,瀏覽器會禁止AJAX訪問不同域的地址。W3C的CORS規範(Cross-originresource sharing)允許實現跨域訪問,並被現在大多數瀏覽器支援,包括:

  Chrome 3+;

  FireFox 3.5+;

  Opera 12+;

  Safari 4+;

  Internet Explorer 8+;

1、攔截器

/**
     * 跨域訪問
     * @param registry 註冊
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("http://domain2.com")
                .allowedMethods("POST", "GET");
    }

格式化

將HTTP請求對映到Controller方法的引數上後,Spring會自動進行型別轉化。對於日期型別的引數,Spring預設並沒有配置如何將字串轉為日期型別。為了支援可按照指定格式轉為日期型別,需要新增一個DateFormatter類:

1、攔截器

/**
     * 格式化
     * @param registry 註冊
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
    }

2、入參

package com.gcz.entity.req;

import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.Date;

/**
 * @author guocz
 * @date 20210623
 * 使用者
 */
@Data
public class UserReq {

    /**
     * 日期
     */
    @NotNull(message = "日期不能為空")
    private Date date;
}

3、呼叫類

package com.gcz.controller;

import com.gcz.entity.req.UserReq;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
 * @author guocz
 * @date 20210621
 * 使用者
 */
@Controller
@RequestMapping("/admin")
public class UserController {

    @ResponseBody
    @RequestMapping("/checkFormatter.json")
    public void checkFormatter(@Validated UserReq req, HttpServletResponse response) throws IOException {
        Date date = req.getDate();
        response.getWriter().write(date.toString());
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().close();
    }
}

4、呼叫格式:

註冊Controller

應用有時候沒必要為一個URL指定一個Controller方法,可以直接將URI請求轉到對模板的渲染上。

例:

package com.gcz.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author guocz
 * @date 20210630
 * 入口
 */
@Controller
@RequestMapping("/")
public class IndexController {
    
    public String index(){
        return "/index.btl";
    }
    
}

可以直接通過ViewControllerRegistry註冊一個

/**
     * 註冊Controller
     * @param registry 註冊
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("index.html").setViewName("/index.btl");
        registry.addRedirectViewController("/**/*.do", "/index.html");
    }