背景:
之前是spring项目,增加了servlet,对应非访问路径如/defA/inner-invoke/operator。
现在改造成了springboot项目后,默认路径是/oprator
希望不改动原有controller代码,让路径能够增加前缀让外面能正常调用。
原web.xml配置:
<!-- Web Servlet Configuration -->
<servlet>
<servlet-name>stariboss</servlet-name>
<servlet-class>com.osgi.web.servlet.SpringProxyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>defA</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>defA</servlet-name>
<url-pattern>/inner-invoke/*</url-pattern>
</servlet-mapping>
<!-- End Web Servlet Configuration -->
方案一、统一增加前缀并增加拦截
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebIntfConfig implements WebMvcConfigurer {
@Autowired
private SessionManagerInterceptor sessionManagerInterceptor;
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/defA/inner-invoke", c -> c.isAnnotationPresent(Controller.class) || c.isAnnotationPresent(RestController.class));
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(sessionManagerInterceptor)
.addPathPatterns("/defA/inner-invoke/**");
registry.addInterceptor(loginCheckInterceptor)
.addPathPatterns("/defA/inner-invoke/**");
}
}
方案二:增加拦截器,然后服务器内部增加请求转发
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MvcRequestInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取原始请求路径
String originalPath = request.getRequestURI();
// 检查请求路径并决定是否需要重定向
if (originalPath.startsWith("/defA/inner-invoke/")) {
// 将请求重定向到新的路径
String newPath = transformUrl(originalPath);
// 获取 RequestDispatcher
RequestDispatcher dispatcher = request.getRequestDispatcher(newPath);
// 在服务器端内部转发请求
dispatcher.forward(request, response);
// 返回 false 表示请求已被处理,不再继续
return false;
}
// 如果不需要重定向,则继续处理请求
return true;
}
private String transformUrl(String currentUrl) {
// 这里实现URL转换逻辑
return currentUrl.replace("/defA/inner-invoke/", "/");
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class IntfInterceptorConfig implements WebMvcConfigurer {
@Autowired
private MvcRequestInterceptor mvcRequestInterceptor;
@Autowired
private SessionManagerInterceptor sessionManagerInterceptor;
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(mvcRequestInterceptor).addPathPatterns("/defA/inner-invoke/**");
registry.addInterceptor(sessionManagerInterceptor).addPathPatterns("/**");
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}
增加其他几个拦截器相关代码
@Component
public class SessionManagerInterceptor extends HandlerInterceptorAdapter {
private final Log logger = LogFactory.getLog(SessionManagerInterceptor.class);
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
preReadRemoteInvocation(request);
return true;
} finally {
preWriteRemoteInvocationResult(response,handler);
}
}
private void preReadRemoteInvocation(HttpServletRequest request) {
String sessionId = request.getHeader("sessionId");
ApplicationSession appSession =null;
if(sessionId!=null && sessionId.length()>0){
appSession = getCache().getSession(sessionId);
if(appSession == null){
if (logger.isWarnEnabled()) {
logger.warn("not find session: " + sessionId);
}
}else{
if (logger.isDebugEnabled()) {
logger.debug("getSession: " + sessionId);
}
}
}
if(appSession==null){
appSession = ApplicationSession.create();
if (logger.isDebugEnabled()) {
logger.debug("create a new Session: " + appSession.getId());
}
}
ApplicationSessionHolder.put(appSession);
}
private void preWriteRemoteInvocationResult(HttpServletResponse response,Object handler) {
ApplicationSession appSession = ApplicationSessionHolder.getApplicationSession();
if (appSession != null) {
if (ApplicationSessionHolder.isClear()
&& !"login".equals(((HandlerMethod)handler).getMethod().getName())) {
if (logger.isInfoEnabled()) {
logger.info("remove cache Session : " + appSession.getId());
}
getCache().clearSession(appSession.getId());
} else {
appSession.updateLastAccessedTime();
response.setHeader("sessionId", appSession.getId());
getCache().putSession(appSession);
}
// ApplicationSessionHolder.remove();
}
}
public ISessionCache getCache() {
if (BeanFactoryHolder.getContext().containsBean("proxySessionCache")) {
return (ISessionCache) BeanFactoryHolder.getContext().getBean("proxySessionCache");
}
return (ISessionCache) BeanFactoryHolder.getContext().getBean("sessionCache");
}
}
package com.star.sms.webconfig;
import com.star.sms.business.core.ApplicationSessionHolder;
import com.star.sms.business.core.BeanFactoryHolder;
import com.star.sms.exceptions.BossInnerServiceInvokeException;
import com.star.sms.model.core.ApplicationSession;
import com.star.sms.remote.session.ISessionCache;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoginCheckInterceptor extends HandlerInterceptorAdapter {
private String[] methods = { "login", "logout", "unlock", "getVersion","getSystemParamInt", "getSession","getSupplyOperatorRecordSwitch" ,"agentLogin"};
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws BossInnerServiceInvokeException {
if (!(handler instanceof HandlerMethod)) {
return true;
}
if (!ArrayUtils.contains(methods, ((HandlerMethod)handler).getMethod().getName()) && !isLogin()) {
String sessionId = request.getHeader("sessionId");
if (StringUtils.hasText(sessionId)) {
ApplicationSession session = getCache().getSession(sessionId);
if (session == null || session.getAttribute("operator") == null) {
throw BossInnerServiceInvokeException.error("not.login");
}else{
session.updateLastAccessedTime();
getCache().putSession(session);
ApplicationSessionHolder.put(session);
}
} else {
throw BossInnerServiceInvokeException.error("not.login");
}
}
return true;
}
public static boolean isLogin() {
ApplicationSession session = ApplicationSessionHolder.getApplicationSession();
if (session == null) {
return false;
}
Object o = session.getAttribute("operator");
return o != null;
}
public ISessionCache getCache() {
if (BeanFactoryHolder.getContext().containsBean("proxySessionCache")) {
return (ISessionCache) BeanFactoryHolder.getContext().getBean("proxySessionCache");
}
return (ISessionCache) BeanFactoryHolder.getContext().getBean("sessionCache");
}
}