思路:
1.自定義注解
2.將用戶信息存儲在session中 ,當然如果是shiro的話直接通過shiro用戶登陸即可。
3.實現HandlerMethodArgumentResolver參數解析類
4.配置攔截器注冊自定義的參數解析器
原理:
用戶登陸 -> 獲取session存儲用戶信息或者shiro登陸
->解析每個請求,判斷是否有自定義注解,有 、解析自定義注解的參數,將session或shiro中的用戶獲取返回給自定義注解中的參數
注意:解析返回的數據類型一定要是自定義注解參數本身或者他的子類
同時攔截器應該實現 WebMvcConfigurer 因為WebMvcConfigurerAdapter已經過期 繼承WebMvcConfigurationSupport也可以(不推薦)
因為:【會使靜態資源失效,靜態資源路徑找不到。需要重寫addResourceHandlers()方法來手動映射路徑:】
在jdk1.8后接口增加了default方法,接口中的方法不必被實現類全部實現,所以直接實現WebMvcConfigurer即可,不需要通過抽象類WebMvcConfigurerAdapter來過渡。
代碼實現:
自定義注解:
import java.lang.annotation.*; /** * * 功能描述: 登錄用戶注解 * * @auther: zhao * @date: 2019/8/1 18:04 * 1.@Target 指定注解的使用范圍,這里我們指定ElementType為PARAMETER,也就是參數即可。 * 2.@Retention作用是定義該注解能保留多久,一共有三種策略,這里我們指定為RUNTIME,也就是運行時。 */ @Retention(RetentionPolicy.RUNTIME) @Target(value = ElementType.PARAMETER) public @interface LoginUser { /** * 當前用戶在session對象中的key,"user" // session.setAttribute("user",one); */ String value() default "user" ; }
自定義參數解析器:
loginUser.value()值就是定義的”user“
import com.could.demo.entity.User; import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; /** * * 功能描述: 登錄用戶的MethodArgumentResolver * * @auther: zhao * @date: 2019/8/1 18:06 */ public class LoginUserMethodArgumentResolver implements HandlerMethodArgumentResolver { /** *若不想自定義注解,可以直接在實現HandlerMethodArgumentResolver的supportsParameter直接返回true 這樣每一個請求過來的都會分解該參數 * 功能描述: 用於判定是否需要處理該參數分解,返回true為需要,並會去調用下面的方法resolveArgument。 * @param: [methodParameter] * @return: boolean * @auther: zhao * @date: 2019/8/1 18:06 * supportsParameter方法, * 判斷什么時候要執行下面的resolveArgument方法。這里我們判斷當一個方法的參數含有@LoginUser * 並且方法的參數是我們的用戶類時返回true。 */ @Override public boolean supportsParameter(MethodParameter methodParameter) { return methodParameter.hasParameterAnnotation(LoginUser.class) && User.class.isAssignableFrom(methodParameter.getParameterType()); // return methodParameter.hasParameterAnnotation(LoginUser.class); } /** * * 功能描述: 真正用於處理參數分解的方法,返回的Object就是controller方法上的形參對象。(獲得登錄用戶信息) * @param: [methodParameter, modelAndViewContainer, nativeWebRequest, webDataBinderFactory] * @return: java.lang.Object * @auther: zhao * @date: 2019/8/1 18:05 * resolveArgument方法,在這里我們直接把放在session中的用戶信息放回去即可。 */ @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { /** * 如果是shiro的話直接通過shiro獲取用戶信息即可 */ LoginUser loginUser = methodParameter.getParameterAnnotation(LoginUser.class); if( loginUser != null){ return nativeWebRequest.getAttribute(loginUser.value(), NativeWebRequest.SCOPE_SESSION); } return null; } }
注冊攔截器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; /** * * 功能描述: 獲得登錄用戶的配置類 *WebMvcConfigurerAdapter已過時 * 在jdk1.8后增加了default,接口中的方法不必被實現類全部實現,所以直接實現WebMvcConfigurer即可,不需要通過抽象類WebMvcConfigurerAdapter來過渡。 * @auther: zhao * @date: 2019/8/1 18:04 */ @Configuration public class LoginUserConfigurer implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { // 注冊loginUserMethodArgumentResolver的參數分解器 argumentResolvers.add(loginUserMethodArgumentResolver()); } @Bean(name = "loginUserMethodArgumentResolver") public LoginUserMethodArgumentResolver loginUserMethodArgumentResolver(){ return new LoginUserMethodArgumentResolver(); } }
有@Configuration的類可以很多,他們加載時會合並,但要注解@Bean(name = "loginUserMethodArgumentResolver")中的name不要重復。
Controller類:
import com.could.demo.config.security.LoginUser; import com.could.demo.entity.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; /** * AUTHOR :zhao * 日期:2020/3/21 20:47 */ @RestController public class UserAnnotationController { @GetMapping("/loginUser") public String login(HttpSession session){ User user = new User(); user.setName("頭皮發麻"); user.setPassword("10086"); session.setAttribute("user",user); return "ok"; } /** * 測試注解是否能拿到值 * @param managers * @return */ @GetMapping(value = "/testUser") public Object testUser(@LoginUser User managers) { return managers; } @GetMapping(value = "/test") public Object test(User managers) { return managers; } }
