赞
踩
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>com.父目录名</groupId>
- <artifactId>父目录名</artifactId>
- <packaging>pom</packaging>
- <version>1.0-SNAPSHOT</version>
-
- <name>父目录项目名</name>
- <description>改成自己的项目名</description>
-
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.5.15</version>
- <relativePath />
- </parent>
-
- <modules>
- <module>前端名</module>
- <module>后端名</module>
- </modules>
-
- <properties>
- <spring.boot.version>2.5.15</spring.boot.version>
- </properties>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- </project>
- <!-- 插件maven-clean-plugin,用于在编译前,清除之前编译的文件、文件夹等,避免残留之前的内容 -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-clean-plugin</artifactId>
- <version>3.1.0</version>
- <configuration>
- <filesets>
- <fileset>
- <!-- 前端资源目录,即:存放前端包目录-->
- <directory>src/main/resources/static</directory>
- </fileset>
- <fileset>
- <!-- Vue项目打包自动生成的dist目录 -->
- <directory>${project.parent.basedir}/vue-ui/dist</directory>
- </fileset>
- </filesets>
- </configuration>
- </plugin>
-
- <!--frontend-maven-plugin为项目本地下载/安装Node和NPM,运行npm install命令-->
- <plugin>
- <groupId>com.github.eirslett</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.6</version>
- <configuration>
- <workingDirectory>${project.parent.basedir}/vue-ui</workingDirectory>
- </configuration>
- <executions>
- <execution>
- <id>install node and npm</id>
- <goals>
- <goal>install-node-and-npm</goal>
- </goals>
- <!-- 改成对应版本 -->
- <configuration>
- <nodeVersion>v16.13.0</nodeVersion>
- <npmVersion>8.1.0</npmVersion>
- </configuration>
- </execution>
- <!-- Install all project dependencies -->
- <execution>
- <id>npm install</id>
- <goals>
- <goal>npm</goal>
- </goals>
- <phase>generate-resources</phase>
- <configuration>
- <arguments>install</arguments>
- </configuration>
- </execution>
- <!-- Build and minify static files -->
- <execution>
- <id>npm run build:prod</id>
- <goals>
- <goal>npm</goal>
- </goals>
- <configuration>
- <arguments>run build:prod</arguments>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- <!--资源插件,主要为了从前端项目里复制打包好的文件到springboot项目-->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <version>3.1.0</version>
- <executions>
- <execution>
- <id>copy static</id>
- <phase>generate-resources</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <!-- 复制前端打包文件到这里 -->
- <outputDirectory>src/main/resources/static</outputDirectory>
- <overwrite>true</overwrite>
- <resources>
- <resource>
- <!-- 从前端打包的目录dist进行指定文件、文件夹内容的复制-->
- <directory>${project.parent.basedir}/vue-ui/dist</directory>
- <includes>
- <!-- 具体根据实际前端代码、及目录结构进行配置-->
- <include>static/css/</include>
- <include>static/fonts/</include>
- <include>static/img/</include>
- <include>static/js/</include>
- <include>favicon.ico</include>
- <include>index.html</include>
- </includes>
- </resource>
- </resources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- package com.pinnacles.framework.config;
-
- import java.util.concurrent.TimeUnit;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.Ordered;
- import org.springframework.http.CacheControl;
- import org.springframework.web.cors.CorsConfiguration;
- import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
- import org.springframework.web.filter.CorsFilter;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
- import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
- import com.pinnacles.common.constant.Constants;
- import com.pinnacles.framework.interceptor.RepeatSubmitInterceptor;
-
- /**
- * 通用配置
- *
- * @author casoft
- */
- @Configuration
- public class ResourcesConfig implements WebMvcConfigurer
- {
- @Autowired
- private RepeatSubmitInterceptor repeatSubmitInterceptor;
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry)
- {
- /** 本地文件上传路径 */
- registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
- .addResourceLocations("file:" + CaSoftConfig.getProfile() + "/");
-
- /** 页面静态化 */
- registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/static/");
-
- /** swagger配置 */
- registry.addResourceHandler("/swagger-ui/**")
- .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
- .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
- }
-
- /*首页规则*/
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/index").setViewName("index.html");
- registry.addViewController("/").setViewName("index.html");
- registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
- }
-
- /**
- * 自定义拦截规则
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry)
- {
- registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
- }
-
- /**
- * 跨域配置
- */
- @Bean
- public CorsFilter corsFilter()
- {
- CorsConfiguration config = new CorsConfiguration();
- config.setAllowCredentials(true);
- // 设置访问源地址
- config.addAllowedOriginPattern("*");
- // 设置访问源请求头
- config.addAllowedHeader("*");
- // 设置访问源请求方法
- config.addAllowedMethod("*");
- // 有效期 1800秒
- config.setMaxAge(1800L);
- // 添加映射路径,拦截一切请求
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", config);
- // 返回新的CorsFilter
- return new CorsFilter(source);
- }
- }
- @Override
- protected void configure(HttpSecurity httpSecurity) throws Exception
- {
- // 注解标记允许匿名访问的url
- ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
- permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
-
- httpSecurity
- // CSRF禁用,因为不使用session
- .csrf().disable()
- // 禁用HTTP响应标头
- .headers().cacheControl().disable().and()
- // 认证失败处理类
- .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
- // 基于token,所以不需要session
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
- // 过滤请求
- .authorizeRequests()
- // 对于登录login 注册register 验证码captchaImage 允许匿名访问
- .antMatchers("/login", "/register", "/captchaImage").permitAll()
- // 静态资源,可匿名访问
- .antMatchers(HttpMethod.GET,"/**/**","/**","/index", "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
- .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
- // 放开Swaggger文档
- .antMatchers("/doc.html","/static/**").anonymous()
- // 放开WebSocket
- .antMatchers("/websocket/**").permitAll()
- // 除上面外的所有请求全部需要鉴权认证
- .anyRequest().authenticated()
- .and()
- .headers().frameOptions().disable();
- // 添加Logout filter
- httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
- // 添加JWT filter
- httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
- // 添加CORS filter
- httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
- httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <artifactId>父目录的pom名</artifactId>
- <groupId>com.父目录</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
-
-
- <groupId>com.父目录.vue-ui</groupId>
- <artifactId>vue-ui</artifactId>
-
-
- </project>
注释之后页面刷新不出现404问题
- # 直接注释掉
- # VITE_APP_ENV = 'production'
- # 直接注释掉或者改为 '/' 都行
- # VITE_APP_BASE_API = '/prod-api'
与后端插件一起使用,按自己的打包结构来自行调整
- build:{
- rollupOptions:{
- output:{
- chunkFileNames: 'static/js/[name]-[hash].js',
- entryFileNames: 'static/js/[name]-[hash].js',
- assetFileNames: (assetInfo) => {
- if (assetInfo.type === 'asset' && /\.(jpe?g|png|gif|svg)$/i.test(assetInfo.name)) {
- return 'static/img/[name].[hash][ext]';
- } if (assetInfo.type === 'asset' && /\.(ttf|woff|woff2|eot)$/i.test(assetInfo.name)) {
- return 'static/fonts/[name].[hash][ext]';
- }
- return 'static/[ext]/name1-[hash].[ext]';
- },
- //manualChunks 两种使用形式
- // manualChunks:{
- // elementPlus:['element-plus']
- // }
- manualChunks(id) {
- if (id.includes('element-plus')) {
- return 'element-plus';
- }
- }
- }
- }
- }
保证页面刷新不丢失
- const router = createRouter({
- //将createWebHistory() 改为 createWebHashHistory()
- // history: createWebHistory(),
- history: createWebHashHistory(),
- routes: constantRoutes,
- scrollBehavior(to, from, savedPosition) {
- if (savedPosition) {
- return savedPosition
- } else {
- return { top: 0 }
- }
- },
- });
完成后,后端点击maven插件自带的package即可自动完成前后端打包+整合
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。