.NET Core 3.1 with ReactJs 16.9.0 - 在 IIS 子文件夹中运行

如何解决.NET Core 3.1 with ReactJs 16.9.0 - 在 IIS 子文件夹中运行

我有一个带有 ReactJs 前端的 .NET Core 3.1(我使用的是 switch 仿生框架),我试图在 IIS 上的子文件夹 (subapp) 中运行它。在 IIS 上安装应用程序作为网站工作正常。该应用程序运行没有问题。但是,当将应用程序安装为 IIS 默认页面下的子应用程序时,将始终在响应需要的任何资源上给出 404。发生这种情况是因为 React 使用的 baseUrl 默认为根 url。

到目前为止,除了将子文件夹名称添加到 baseurl 本身之外,我还没有找到改变这种行为的方法。这对我来说不是解决方案,因为这个应用程序将安装在 1 台服务器上的 IIS 下的至少 43 个子文件夹中。我无法仅仅因为必须更新子文件夹而构建和部署 43 多个应用程序!

有没有人知道如何让 React 前端识别正在使用的当前 url(包括子文件夹),而不仅仅是默认为根 url?

我尝试设置“主页”:“。”和 "homepage": "./" in package.json,根据 'gaearon' (https://github.com/facebook/create-react-app/issues/527) 的帖子,但它没有影响。

我的配置文件 (default.tsx) 如下所示(于 2021/04/09 编辑):

import Project from '../src/globals/interfaces/Project';

const isDevelopment = Object.is(process.env.NODE_ENV,'development');

const baseUrl = isDevelopment ? 'http://localhost:5105' : '.';

const config: IConfigData<Project,{}> = {
  core: {
    i18n: {
      defaultLocale: 'en',},project: {
    baseUrl,runtime: {},};

export default config;

我的 package.json:

{
  "name": "MyApp","version": "3.4.2","description": "My Application","license": "Whatever","author": {
    "name": "Werner"
  },"config": {
    "AppIcon": "./src/assets/appIcon/logo.png","title": "My App Title","devServer": {
      "host": "0.0.0.0","port": "5170","https": false,"publicPath": "/"
    },"publicPath": "","homepage": ".","functionalTestBrowsers": [
      "chrome","firefox","internet explorer","edge"
    ]
  },"scripts": {
    "test": "jest --no-cache","test:update": "jest --updateSnapshot","start": "webpack-dev-server --env.build=dev","start:4110": "webpack-dev-server --env.build=dev --env.config=4110","start:4120": "webpack-dev-server --env.build=dev --env.config=4120","start:4130": "webpack-dev-server --env.build=dev --env.config=4130","start:4140": "webpack-dev-server --env.build=dev --env.config=4140","start:4150": "webpack-dev-server --env.build=dev --env.config=4150","start:legacy": "webpack-dev-server --env.build=dev --env.legacy=true --env.REDUX_TOOLS=logger","start:swidget": "webpack-dev-server --port 7070 --env.build=dev --env.swidget=true --env.legacy=true --env.REDUX_TOOLS=logger","start:host": "webpack-dev-server --env.build=dev --env.legacy=true --env.exposed=true --env.REDUX_TOOLS=logger","build": "webpack --env.build=prod --env.verbose=false","build:ci": "webpack --env.build=prod --env.verbose=true --env.release=true","build:legacy": "webpack --env.build=prod --env.legacy=true","build:host": "webpack --env.build=prod --env.legacy=true --env.exposed=true","build:swidget": "webpack --env.build=prod --env.swidget=true --env.legacy=true","build:multi": "webpack --env.build=multi","build:test:functional": "tsc -p test/functional/tsconfig.json","lint": "nyr lint:eslint && nyr lint:stylelint && nyr lint:prettier","lint:staged": "lint-staged","lint:eslint": "eslint --ext ts,tsx src","lint:prettier": "prettier --check \"./**/*\"","lint:stylelint": "stylelint \"src/**/*.(css|scss)\" --syntax scss","lint:fix": "nyr lint:fix:eslint && nyr lint:fix:stylelint && nyr lint:fix:postcss && nyr lint:fix:prettier","lint:fix:prettier": "prettier --write \"./**/*\"","lint:fix:postcss": "postcss --config postcss.config.js --env sort-only --no-map --replace \"src/**/*.(css|scss)\"","lint:fix:stylelint": "stylelint \"src/**/*.(css|scss)\" --syntax scss --fix","lint:fix:eslint": "eslint --fix --ext ts,"clean": "rimraf dist && rimraf coverage","storybook": "cross-env build=dev start-storybook -p 9001 -c .build/storybook","storybook:static": "cross-env build=prod build-storybook -c .build/storybook -o dist/storybook","test:functional": "run-p build:test:functional test:functional:selenium && run-p --race start wdio","test:functional:headless": "run-p build:test:functional test:functional:selenium && run-p --race start wdio:headless","test:functional:selenium": "selenium-standalone install --silent","wdio": "wdio .build/wdio.conf.js","wdio:headless": "cross-env WDIO_HEADLESS=true wdio .build/wdio.conf.js"
  },"husky": {
    "hooks": {
      "pre-commit": "lint-staged","post-commit": "git update-index --again"
    }
  },"repository": {
    "type": "git","url": "Don't worry! Taken out for security!"
  },"engines": {
    "node": ">=8.11.3","npm": ">=5.6.0"
  },"browserslist": [
    "> 1%","last 2 versions","Firefox ESR","ie >= 11"
  ],"dependencies": {
    "@daimler/material-ui-comps": "0.0.4-release-84.0","@daimler/material-ui-theme": "0.0.9","@daimler/typeface-daimler-cs-web": "^1.0.0","@material-ui/core": "^4.11.0","@material-ui/icons": "^4.9.1","@material-ui/lab": "^4.0.0-alpha.53","@switch/core": "2.0.0-beta.2","@types/react-csv": "^1.1.1","@types/react-router-dom": "^5.1.3","@types/redux-logger": "^3.0.7","axios": "^0.19.0","core-js": "~3.2.1","domtokenlist-shim": "~1.2.0","file-saver": "^2.0.2","inversify": "~4.3.0","joi-browser": "~13.4.0","jwt-decode": "^2.2.0","material-table": "^1.69.1","material-ui-dropzone": "^3.2.1","react": "~16.9.0","react-csv": "^2.0.3","react-dom": "~16.9.0","react-hot-loader": "~4.12.11","react-promise-tracker": "^2.0.5","react-redux": "^7.2.0","react-router-dom": "^5.1.2","react-switch": "^5.0.1","react-table": "^7.5.1","react-transition-group-v2": "^4.3.0","redux": "^4.0.5","redux-devtools-extension": "^2.13.8","redux-logger": "^3.0.6","redux-thunk": "^2.3.0","regenerator-runtime": "~0.13.3","tslib": "~1.10.0","typesafe-actions": "^5.1.0","universal-cookie": "^4.0.3","whatwg-fetch": "~3.0.0"
  },"devDependencies": {
    "@babel/core": "~7.5.5","@babel/preset-env": "~7.5.5","@babel/runtime": "~7.5.5","@hot-loader/react-dom": "~16.9.0","@storybook/addon-actions": "~5.1.11","@storybook/addon-info": "~5.1.11","@storybook/addon-knobs": "~5.1.11","@storybook/addon-links": "~5.1.11","@storybook/addons": "~5.1.11","@storybook/cli": "~5.1.11","@storybook/react": "~5.1.11","@types/enzyme": "~3.10.3","@types/jasmine": "~3.4.0","@types/jest": "~24.0.18","@types/jwt-decode": "^2.2.1","@types/node": "~12.0.0","@types/prop-types": "~15.7.1","@types/react": "~16.9.2","@types/react-dom": "~16.9.0","@types/react-redux": "^7.1.7","@types/react-test-renderer": "~16.9.0","@types/storybook__addon-actions": "~3.4.3","@types/storybook__addon-info": "~4.1.2","@types/storybook__addon-knobs": "~5.0.3","@types/storybook__addon-links": "~3.3.5","@types/storybook__react": "~4.0.2","@typescript-eslint/eslint-plugin": "~2.0.0","@typescript-eslint/parser": "~2.0.0","@wdio/cli": "~5.12.4","@wdio/dot-reporter": "~5.12.1","@wdio/jasmine-framework": "~5.12.1","@wdio/local-runner": "~5.12.4","@wdio/selenium-standalone-service": "~5.12.1","@wdio/spec-reporter": "~5.12.1","@wdio/sync": "~5.12.3","babel-loader": "~8.0.6","clean-webpack-plugin": "~3.0.0","copy-webpack-plugin": "~5.0.4","cross-env": "~5.2.0","css-loader": "~3.2.0","css-modules-typescript-loader": "~3.0.0","cssjson": "~2.1.3","duplicate-package-checker-webpack-plugin": "~3.0.0","enzyme": "~3.10.0","enzyme-adapter-react-16": "~1.14.0","enzyme-to-json": "~3.4.0","eslint": "~6.2.1","eslint-config-prettier": "~6.1.0","eslint-plugin-prettier": "~3.1.0","eslint-plugin-react": "~7.14.3","expose-loader": "~0.7.5","fork-ts-checker-webpack-plugin": "~1.5.0","html-webpack-multi-build-plugin": "~1.0.0","html-webpack-plugin": "~3.2.0","husky": "~3.0.4","identity-obj-proxy": "~3.0.0","imagemin-lint-staged": "~0.4.0","jasmine": "~3.4.0","jest": "~24.9.0","lint-staged": "~9.2.3","mini-css-extract-plugin": "~0.8.0","mock-local-storage": "~1.1.8","npm-run-all": "~4.1.5","nyr": "1.1.0","optimize-css-assets-webpack-plugin": "~5.0.3","postcss": "~7.0.17","postcss-cli": "~6.1.3","postcss-extend": "~1.0.5","postcss-import": "~12.0.1","postcss-import-sync": "~7.1.4","postcss-loader": "~3.0.0","postcss-nested": "~4.1.2","postcss-preset-env": "~6.7.0","postcss-remove-prefixes": "~1.2.0","postcss-sorting": "~5.0.1","postcss-unprefix": "~2.1.4","prettier": "~1.18.2","react-ace": "^7.0.4","react-docgen-typescript-loader": "~3.1.1","react-test-renderer": "~16.9.0","rimraf": "~3.0.0","simple-progress-webpack-plugin": "~1.1.2","style-loader": "~1.0.0","stylelint": "~10.1.0","stylelint-config-css-modules": "~1.4.0","stylelint-config-recommended": "~2.2.0","terser-webpack-plugin": "~1.4.1","ts-jest": "~24.0.2","ts-loader": "~6.0.4","typescript": "~3.5.3","url-loader": "~2.1.0","webapp-webpack-plugin": "~2.7.1","webpack": "~4.39.2","webpack-cli": "~3.3.7","webpack-dev-server": "~3.8.0","webpack-merge": "~4.2.1"
  }
}

任何帮助将不胜感激。

解决方法

互联网上有 100 多篇关于如何获取 ReactJS 前端的帖子,作为 asp.net 核心后端的一部分,在 IIS 子文件夹下正常运行。他们中的大多数都是一样的。其中一些确实可以正常工作,而另一些则只是垃圾。

如果您想在子文件夹中运行应用程序(后端和前端),那么唯一的方法就是在 React 中硬编码基本 url 和公共路径。

由于我将 React 与 typescript 和 switch 框架一起使用,所以我可以这样做: 默认.tsx:

const baseUrl = isDevelopment ? 'http://localhost:5105' : 'http://localhost/MySubFolderName';

然后在 package.json 中:

"publicPath": "MySubFolderName",

为生产构建后,应用程序将在 IIS 子文件夹中正常运行。

但我的目标是让这个应用程序在 40 多个 IIS 子文件夹中运行,其中许多在同一台服务器上。并且绝对不是为每个安装单独构建前端的选项。想想维护的噩梦!!

因此我决定编写一个脚本来为我更改所需的文件。自动!

我尝试的第一个选项是在 index.html 中设置基本标签 <base href="/">,互联网上的许多帖子都给出了解决方案。我的脚本打开了这个 index.html 并替换了标签以包含子文件夹名称:<base href="/MySubFolderName/">

“瞧瞧”,网站运行起来了!然而,当 2 天后我终于发现这还不够时,我感到非常失望。站点运行,但路由中断!无论您使用哪种路由器包。

因此,注意,仅在基本标签中设置 href 还不够

我的最终解决方案: 编辑: 我的第一个解决方案是对基本 url 和公共路径进行硬编码,但使用我的特殊名称:XYXYX。

经过进一步思考后,我决定不对任何内容进行硬编码,而是保持前端不变。后端现在会根据需要更新所需的文件,确保它们对于“端口”安装或“子文件夹”安装是正确的。

在后端,在 Programs.cs 中,创建一个函数,该函数将根据应用程序是否安装在 IIS 下以在端口上运行来更改 index.html 和 *app.js 文件(例如 http:/ /domain:port) 或在子文件夹中(例如 http://domain/subfolder)。

appsettings.json:

"AppAddress": "http://my.domain.name/MySubFolderName",

Program.cs:

...
            IConfiguration Configuration = new ConfigurationBuilder()
                .SetBasePath(pathToContentRoot)
                .AddJsonFile("appsettings.json",optional: false,reloadOnChange: true)
                .AddJsonFile($"appsettings.{env}.json",optional: true,reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();

            try
            {
                var host = CreateHostBuilder(args).Build();
...
...
                try
                {
                    UpdateFilesForSubfolderOrPortUse(Configuration["AppAddress"],pathToContentRoot);
                }
                catch (Exception e)
                {
                    Log.Fatal(e,$"Host terminated. Could not rewrite files! Error: {e.Message}");
                    return 1;
                }

                host.Run();
...
...
        private static void UpdateFilesForSubfolderOrPortUse(string serverAddress,string pathToContentRoot)
        {
            string subFolder = ExtractSubfolderName(serverAddress);

            // First extract the search-string from the *app.js file
            string searchString = ExtractSearchStringFromJsFile(pathToContentRoot);
            string oldSubFolder = "";

            if (searchString != ".")
            {
                oldSubFolder = searchString.Substring(searchString.IndexOf("/",searchString.IndexOf("://") + 3) + 1);
            }

            Dictionary<string,string> searchAndReplaceDict = new Dictionary<string,string>
            {
                { "HtmlSearchString1","" },{ "HtmlReplaceString1",{ "HtmlSearchString2",{ "HtmlReplaceString2",{ "JsSearchString1",{ "JsReplaceString1",{ "JsSearchString2",{ "JsReplaceString2",{ "JsSearchString3",{ "JsReplaceString3","" }
            };

            if ((string.IsNullOrEmpty(subFolder) && searchString == ".") || (!string.IsNullOrEmpty(subFolder) && oldSubFolder == subFolder))
            {
                // No conversion is needed
                return;
            }
            else if ((!string.IsNullOrEmpty(subFolder) && searchString == "."))
            {
                // Convert from Port to SubFolder
                searchAndReplaceDict["HtmlSearchString1"] = "link href=\"";
                searchAndReplaceDict["HtmlReplaceString1"] = $"link href=\"{subFolder}/";
                searchAndReplaceDict["HtmlSearchString2"] = "src=\"";
                searchAndReplaceDict["HtmlReplaceString2"] = $"src=\"{subFolder}/";
                searchAndReplaceDict["JsSearchString1"] = "+\"fonts/";
                searchAndReplaceDict["JsReplaceString1"] = "+\"/fonts/";
                searchAndReplaceDict["JsSearchString2"] = "},i.p=\"";
                searchAndReplaceDict["JsReplaceString2"] = "},i.p=\"" + subFolder;
                searchAndReplaceDict["JsSearchString3"] = "\"http://localhost:5105\":\".";
                searchAndReplaceDict["JsReplaceString3"] = $"\"http://localhost:5105\":\"{(serverAddress[serverAddress.Length - 1] == '/' ? serverAddress.Substring(0,serverAddress.Length - 1) : serverAddress)}";
            }
            else if ((!string.IsNullOrEmpty(subFolder) && searchString != "."))
            {
                // Convert from SubFolder to SubFolder
                searchAndReplaceDict["HtmlSearchString1"] = oldSubFolder;
                searchAndReplaceDict["HtmlReplaceString1"] = subFolder;
                searchAndReplaceDict["JsSearchString1"] = "+\"fonts/";
                searchAndReplaceDict["JsReplaceString1"] = "+\"/fonts/";
                searchAndReplaceDict["JsSearchString2"] = $"\"{oldSubFolder}\"";
                searchAndReplaceDict["JsReplaceString2"] = $"\"{subFolder}\"";
                searchAndReplaceDict["JsSearchString3"] = $"/{oldSubFolder}\"";
                searchAndReplaceDict["JsReplaceString3"] = $"/{subFolder}\"";
            }
            else
            {
                // Convert from SubFolder to Port
                searchAndReplaceDict["HtmlSearchString1"] = $"{oldSubFolder}/";
                searchAndReplaceDict["JsSearchString1"] = "+\"/fonts/";
                searchAndReplaceDict["JsReplaceString1"] = "+\"fonts/";
                searchAndReplaceDict["JsSearchString2"] = $"\"{oldSubFolder}\"";
                searchAndReplaceDict["JsReplaceString2"] = "\"\"";
                searchAndReplaceDict["JsSearchString3"] = searchString;
                searchAndReplaceDict["JsReplaceString3"] = $".";
            }

            DoUpdateFiles(searchAndReplaceDict,pathToContentRoot);
        }

        private static string ExtractSubfolderName(string serverAddress)
        {
            string baseAddr = serverAddress.Substring(serverAddress.IndexOf("://") + 3);
            int idx = baseAddr.IndexOf('/');
            string subaddr = "";

            if (idx > 0)
            {
                subaddr = baseAddr.Substring(idx + 1);

                if (subaddr.Length > 0 && subaddr[subaddr.Length - 1] == '/')
                {
                    subaddr = subaddr.Substring(0,subaddr.Length - 1);
                }
            }

            return subaddr;
        }

        private static string ExtractSearchStringFromJsFile(string pathToContentRoot)
        {
            string rootfolder = $"{pathToContentRoot}\\App";
            var exts = new[] { "app.js" };
            IEnumerable<string> files = Directory
                .EnumerateFiles(@rootfolder,"*.*",SearchOption.TopDirectoryOnly)
                .Where(file => exts.Any(x => file.EndsWith(x,StringComparison.OrdinalIgnoreCase)));

            string jsContents = File.ReadAllText(files.First());
            string searchFor = "project:{baseUrl:Object.is(\"production\",\"development\")?\"http://localhost:5105\":\"";

            string tmpSearchStr = jsContents.Substring(jsContents.IndexOf(searchFor) + searchFor.Length);

            if (tmpSearchStr.StartsWith(".\""))
            {
                // This is a Port installation
                tmpSearchStr = ".";
            }
            else
            {
                // This is a SubFolder installation
                tmpSearchStr = tmpSearchStr.Substring(0,tmpSearchStr.IndexOf("\"}"));
            }

            return tmpSearchStr;
        }

        private static void DoUpdateFiles(Dictionary<string,string> searchAndReplaceDict,string pathToContentRoot)
        {
            string rootfolder = $"{pathToContentRoot}\\App";
            var exts = new[] { ".html","app.js" };
            IEnumerable<string> files = Directory
                .EnumerateFiles(@rootfolder,StringComparison.OrdinalIgnoreCase)));

            foreach (string file in files)
            {
                string contents = File.ReadAllText(file);

                if (Path.GetExtension(@file) == ".html")
                {
                    contents = contents.Replace(searchAndReplaceDict["HtmlSearchString1"],searchAndReplaceDict["HtmlReplaceString1"]);

                    if (!string.IsNullOrEmpty(searchAndReplaceDict["HtmlSearchString2"]))
                    {
                        contents = contents.Replace(searchAndReplaceDict["HtmlSearchString2"],searchAndReplaceDict["HtmlReplaceString2"]);
                    }
                }
                else if (Path.GetExtension(@file) == ".js")
                {
                    contents = contents.Replace(searchAndReplaceDict["JsSearchString1"],searchAndReplaceDict["JsReplaceString1"]);
                    contents = contents.Replace(searchAndReplaceDict["JsSearchString2"],searchAndReplaceDict["JsReplaceString2"]);
                    contents = contents.Replace(searchAndReplaceDict["JsSearchString3"],searchAndReplaceDict["JsReplaceString3"]);
                }

                // Make file writable
                File.SetAttributes(file,FileAttributes.Normal);

                File.WriteAllText(file,contents);
            }
        }

现在管理员可以下载应用程序的版本并将其安装在 IIS 子文件夹中。该管理员还可以将所有文件从一个子文件夹/端口安装复制到另一个。在这两种情况下,管理员都必须使用正确的地址更新配置文件。

应用程序现在将在启动期间,在运行应用程序之前读取 2 个文件并替换所需的字符串。

该应用程序现在使用“标准”前端用于“端口”安装,并使用“硬编码”前端用于“子文件夹”安装,但该前端是动态的并根据具体情况自动更新在“子文件夹名称”上!而且我可以继续在子文件夹或端口中添加新应用程序,而无需每次都重新构建,也无需手动更新所需的字符串以使其运行......

是的,有些人会说这是一种 hack,但在 SW 中,如果没有其他任何东西,即使是 hack 也是一个很好的解决方案!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-