最近在做个练习项目,springboot嵌套vue,将vue的index页面放在springboot的resource下的某目录中。我自己叫这种模式是伪前后端分离。
我的实现方式是
1. 将Vue相关文件包括index页面放在stacie文件下
2.修改配置中静态文件访问的根路径,以及页面加载根路径。(同时注意file:src这种方式在linux服务器上不能识别)
#linux路径必须这么配置,否则找不到首页文件
spring.freemarker.template-loader-path=classpath:/static/
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=rc
# 页面后缀
spring.freemarker.suffix=.html
# static resources
# win可以这么配置
#spring.resources.static-locations=file:src/main/resources/static/
#linux路径必须这么配置,否则找不到静态文件
spring.resources.static-locations=classpath:/static/
spring.resources.cache-period=0
3.完成配置后,创建controller方法,
代码:
@RequestMapping(value = "/")
public String index(HttpServletRequest request, String r, Model model, Device device){
LOGGER.debug("#### 用户设备类型:电脑{}, 手机{}, 平板{}",device.isNormal(),device.isMobile(),device.isTablet());
//跳转被拦截的地址,可能为空
model.addAttribute("r",r);
//判断浏览器是否是PC端
if(device.isNormal()){
model.addAttribute("deviceNormal",true);
model.addAttribute("isWx",false);
return "index";//pc
}else{
//可能是手机也可能是平板(手机mobile, 平板tablet)
model.addAttribute("deviceNormal",false);
model.addAttribute("isWx", HttpRequestUtils.isWeixin(request));
// return "index/default-mobile";//移动
return "index";//移动
}
}
启动服务,访问 localhost:8080 后直接跳转到index页面。
接下来,在开启swagger2生成api文档时遇到了问题。按照swagger配置方式,
参见:https://blog.csdn.net/sanyaoxu_2/article/details/80555328
但是我的项目中访问不到swagger页面,显示404。根据网上搜索的结果提示,需要加载swagger配置类实现
WebMvcConfigurationSupport并重写addResourceHandlers()方法指定其默认跟路径。见图片,
项目后swagger可成功访问。但是 @RequestMapping(value = "/") 失效,直接访问localhost:8080时项目报错。
后来研究了一下各位大神博客上的介绍,终于找到一个解决问题的办法
是因为WebMvc配置类中没有生效,导致拦截器未生效。
解决办法是直接将swagger配置写在WebMvc中,见代码
package com.supervise.emall.config;
import com.supervise.common.session.SharedUserArgumentResolver;
import com.supervise.emall.interceptor.AddCorsHeadersInterceptor;
import com.supervise.emall.interceptor.AdminSecurityInterceptor;
import com.supervise.emall.interceptor.UserSecurityInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
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.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.List;
/**
* @author BaiTianShi 2017-10-31
*/
@Configuration
@EnableSwagger2
public class DispatcherConfig extends WebMvcConfigurerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherConfig.class);
@Bean
public AdminSecurityInterceptor securityHandlerInterceptor(){
return new AdminSecurityInterceptor();
}
@Bean
public UserSecurityInterceptor qrSecurityHandlerInterceptor(){
return new UserSecurityInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LOGGER.info("######## 配置拦截器... ########");
AdminSecurityInterceptor interceptor = securityHandlerInterceptor();
InterceptorRegistration interceptorRegistration = registry.addInterceptor(interceptor).addPathPatterns("/**");
for(String exUrl:AdminSecurityInterceptor.URL_EXCLUDE_LIST){
interceptorRegistration.excludePathPatterns(exUrl);
}
//-- 开发测试使用, 跨域
AddCorsHeadersInterceptor addCorsHeadersInterceptor = new AddCorsHeadersInterceptor();
InterceptorRegistration corsRegistration = registry.addInterceptor(addCorsHeadersInterceptor);
for(String exUrl:AddCorsHeadersInterceptor.PATTERNS_NEEDED){
corsRegistration.addPathPatterns(exUrl);
}
}
@Bean
public SharedUserArgumentResolver sharedUserArgumentResolver() {
return new SharedUserArgumentResolver();
}
@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(sharedUserArgumentResolver());
}
//swagger 相关
@Value("${swagger.enable}")
private boolean swaggerEnable;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(swaggerEnable)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.supervise.emall.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("接口总览")
.description("测试")
.version("1.0")
.build();
}
/**
* 防止@EnableMvc把默认的静态资源路径覆盖了,手动设置的方式
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 解决静态资源无法访问
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/");
// 解决swagger无法访问
registry.addResourceHandler("/swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
// 解决swagger的js文件无法访问
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
参考:https://blog.csdn.net/zyc8715150/article/details/86693754