/* * Copyright (c) 2016-2017, Guangshan ([email protected]) and the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mxixm.fastboot.weixin.mvc.param; import com.mxixm.fastboot.weixin.annotation.WxMapping; import com.mxixm.fastboot.weixin.module.menu.WxMenu; import com.mxixm.fastboot.weixin.module.user.WxUser; import com.mxixm.fastboot.weixin.module.user.WxUserProvider; import com.mxixm.fastboot.weixin.module.web.WxRequest; import com.mxixm.fastboot.weixin.module.web.WxRequestBody; import com.mxixm.fastboot.weixin.module.web.session.WxSession; import com.mxixm.fastboot.weixin.util.WxWebUtils; import com.mxixm.fastboot.weixin.web.WxUserManager; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ValueConstants; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver; import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.multipart.support.MultipartResolutionDelegate; import javax.servlet.http.HttpServletRequest; /** * FastBootWeixin WxArgumentResolver * * @author Guangshan * @date 2017/8/12 22:51 * @since 0.1.2 */ public class WxArgumentResolver extends AbstractNamedValueMethodArgumentResolver { // 是否有更好的方式?有空参看源码 private WxUserProvider wxUserProvider; private WxUserManager wxUserManager; /** * 从谁发的,也不要了,用一个处理 */ @Deprecated public static final String WX_FROM_USER = "fromUser"; // 默认同上,另外一个参数名 public static final String WX_USER = "wxUser"; /** * 发给谁的,不需要了,用ResponseBodyAdvice处理这个 */ @Deprecated public static final String WX_TO_USER = "toUser"; public WxArgumentResolver(WxUserManager wxUserManager, WxUserProvider wxUserProvider) { super(); this.wxUserManager = wxUserManager; this.wxUserProvider = wxUserProvider; } /** * @param beanFactory a bean factory used for resolving ${...} placeholder * and #{...} SpEL expressions in default values, or {@code null} if default * values are not expected to contain expressions */ public WxArgumentResolver(ConfigurableBeanFactory beanFactory) { super(beanFactory); this.wxUserManager = beanFactory.getBean(WxUserManager.class); this.wxUserProvider = beanFactory.getBean(WxUserProvider.class); } @Override public boolean supportsParameter(MethodParameter parameter) { // 只有method上有注解WxMapping时才支持解析 return AnnotatedElementUtils.hasAnnotation(parameter.getMethod(), WxMapping.class); } @Override protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { return new RequestParamNamedValueInfo(); } /** * 所有的转换都卸载了一起,有空可以分离为多个,抽象一层 * * @param name * @param parameter * @param request * @return the result * @throws Exception */ @Override protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); WxRequest wxRequest = WxWebUtils.getWxRequestFromRequest(servletRequest); // 类型匹配,直接返回 if (parameter.getParameterType() == WxRequest.class) { return wxRequest; } if (parameter.getParameterType() == WxRequest.Body.class) { return wxRequest.getBody(); } if (parameter.getParameterType() == WxMenu.Button.class) { return wxRequest.getButton(); } if (parameter.getParameterType() == WxUser.class) { return wxUserManager.getWxUser(wxRequest.getBody().getFromUserName()); } if (WxSession.class.isAssignableFrom(parameter.getParameterType())) { return wxRequest.getWxSession(); } if (WxRequestBody.class.isAssignableFrom(parameter.getParameterType())) { return WxRequestBody.of((Class) parameter.getParameterType(), wxRequest.getBody()); } // 如果可以获取用户则返回用户 Object user = getUser(parameter, wxRequest); if (user != null) { return user; } return wxRequest.getParameter(name); } protected Object getUser(MethodParameter parameter, WxRequest wxRequest) { // 类型不匹配直接返回 if (!wxUserProvider.isMatch(parameter.getParameterType())) { return null; } else if (WX_USER.equals(parameter.getParameterName()) || !BeanUtils.isSimpleProperty(parameter.getParameterType())) { // 两个都转换失败时,判断是否是简单属性,如果不是,则尝试转换为用户 // 因为此时无法得知是要获取to还是from,所以取对于用户来说更需要的from return wxUserProvider.getUser(wxRequest.getBody().getFromUserName()); } return null; } /* if (WX_TO_USER.equals(parameter.getParameterName())) { // 尝试转换toUser return wxUserProvider.getToUser(wxRequest.getToUser()); } else if (WX_FROM_USER.equals(parameter.getParameterName())) { // 尝试转换fromUser return wxUserProvider.getFromUser(wxRequest.getFromUser()); } */ @Override protected void handleMissingValue(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); if (MultipartResolutionDelegate.isMultipartArgument(parameter)) { if (!MultipartResolutionDelegate.isMultipartRequest(servletRequest)) { throw new MultipartException("Current request is not a multipart request"); } else { throw new MissingServletRequestPartException(name); } } else { throw new MissingServletRequestParameterException(name, parameter.getNestedParameterType().getSimpleName()); } } private static class RequestParamNamedValueInfo extends NamedValueInfo { public RequestParamNamedValueInfo() { super("", false, ValueConstants.DEFAULT_NONE); } public RequestParamNamedValueInfo(RequestParam annotation) { super(annotation.name(), annotation.required(), annotation.defaultValue()); } } }