Nutzboot简介:
NutzBoot为一个基于Nutz框架的微服务方案,以下简称NB!其余略...
NB文档简介:http://www.nutzam.com/core/bo...
简介:
首先关于Nutz以及NB,shiro等介绍以及微服务的概念在此略过,本文中介绍的方法基于Nutz框架,但实现思路和核心类应该可以在其他框架中通用.
一.首先阐述一下研究这个东西的出发点.
一开始在NB中也是使用的shiro.ini配置文件完成对shiro的配置的,但是在实际开发过程中发现,在配置微服务的过程中,shiro文件需要配置或复制多次,这里插一嘴我们的实现方式,我们服务的实现方式为,所有需要独立部署的服务器都会实现同一个基础服务器运行库,来完成通用配置等.
在配置多个服务器的时候发现不同服务器之间如果只使用一个shiro.ini配置文件会出现,[urls]配置下的url重复的情况,即例如前后台的/user/login接口,既是在NB的配置中配置不同服务器上下文,也无法避免同一个shiro配置文件出现此问题
为了解决这个问题其实也想过将不同服务的配置文件分离(当然这在NB结构中是可以实现的),但是出现shiro.ini中[main]等配置被复制多次的情况,不美观也不利于修改.
二.解决思路
为了解决这个问题其实一开始想到的是通过NB中shiro-stater中已有的 shiro.ini.urls 配置解决(这个配置允许在其他一个文件中手写shiro urls 配置列表)
后来发现这个配置无法和 shiro.ini配置文件一起使用(这个配置大概是给使用默认配置的同学使用的)
而已有的shiro大部分配置都在shiro.ini配置文件中,不太可能写成代码形式,只能另寻他法
最后经过几经寻找,最终确定能解决这个问题的方法是(也修改了很多次,这里说了最后两种)
1.复制shiro-starter源码,利用其中已有的重写shiro的 EnvironmentLoaderListener的类,以和之前部分相同的逻辑初始化Shiro.
2.修改上述Listener在传入Environment处做修改(此处省略了starter获取配置文件路径并传入的部分,以及配置非空部分),传入一个重写的Environment,这个重写的类中大部分实现逻辑是由 shiro处理源码IniWebEnvironment类复制过来的,用来完成 shiro.ini文件的配置加载.
3.修改重写类代码,使其可以获取到NB starter的配置(略,用来传入路径或urls),并修改源码中获取Filter的方法createFilterChainResolver()
在其创建Filter实例之前插入代码
1
2
3ini.load(String);
源码:(此处检查了是否有 urls和filter配置)
1
2
3
4
5
6
7
8
9
10// only create a resolver if the 'filters' or 'urls' sections are defined: Ini.Section urls = ini.getSection(IniFilterChainResolverFactory.URLS); Ini.Section filters = ini.getSection(IniFilterChainResolverFactory.FILTERS); if (!CollectionUtils.isEmpty(urls) || !CollectionUtils.isEmpty(filters)) { // either the urls section or the filters section was defined. Go ahead and create the resolver: IniFilterChainResolverFactory factory = new IniFilterChainResolverFactory(ini, this.objects); resolver = factory.getInstance(); }
修改后的代码(此处需要注意我们逻辑中没有 filter配置,这里就没判断)
1
2
3
4
5
6
7
8
9//urls为符合 ini语法的字符串 例如 /user/login = anon String iniUrls = "[urls]rn" + urls; ini.load(iniUrls); // 此代码前,在此处ini会被加载成类 // ini对象在此方法之前就存在,this.object则由父类中负责 IniFilterChainResolverFactory factory = new IniFilterChainResolverFactory(ini, this.objects); resolver = factory.getInstance();
这里需要注意在调用 ini.load后原文件中的 [urls] 配置会被覆盖,而当只有[urls] 但并没有实际内容时并不会被覆盖(没试过空行,请注意)
4.在完成这段代码后发现代码非常难看,shiro urls被配置到了java文件中,为了避免这个问题使用了NB-start直接带的配置方式以及已经存在的 shiro.ini.urls属性,将配置文件中的 urls传入代码中
所以在NB中就成了这样
1
2
3
4
5
6
7
8
9
10
11//获取配置文件中urls String urls = conf.get(ShiroEnvStarter.PROP_INIT_URLS, null); //urls为符合 ini语法的字符串 例如 /user/login = anon String iniUrls = "[urls]rn" + urls; ini.load(iniUrls); // 此代码前,在此处ini会被加载成类 // ini对象在此方法之前就存在,this.object则由父类中负责 IniFilterChainResolverFactory factory = new IniFilterChainResolverFactory(ini, this.objects); resolver = factory.getInstance();
在NB的application.properties配置文件中写法为
1
2
3
4
5
6shiro.ini.urls: /unathenticated = anon /user/login = anon #end
这里还要手动@并感谢下 @wendal @nutzcn
之前并不知道application.properties中多行的写法
至此,整个在代码中覆盖 shiro urls 配置的思路基本就完成了,只剩下一些类似于非空判断参数获取的代码.在此实现下即可实现项目中Shiro main配置为统一文件,而urls配置为专用单独文件
之后要介绍的就是优化部分以及,完整代码
三.优化(完全基于NB)
1.在使用中发现虽然现在 urls已经可以独立文件配置,但多行之间并不可以写注解(在NB层就不会读取完整),并且和 shiro.ini中语法并不完全一样.
最后解决办法为:在项目中添加另一个.ini的配置文件,并在项目中读取ini文件并使用 ini.load加载
2.在添加了ini配置文件后发现最好可以有一部分urls可以通用配置,另一部分可以独立配置.
最后解决方式为:添加两个shiro-url.ini配置文件,并在代码中读取并拼接,在库服务中添加,一个ini文件,并在每个独立的服务中添加完全同路径和名称的文件,使用其打包时互相覆盖的特性,达到独立配置的目的,而另一个不进行覆盖达到通用配置的目的.
而在NB中通过在 starter源码中添加新的配置达到url可以配置并传入的目的.
1
2
3
4
5
6@PropDoc(value = "urls过滤清单ini文件1路径") public static final String PROP_INIT_URLS_PATH1 = "shiro.ini.urls.path1"; @PropDoc(value = "urls过滤清单ini文件2路径") public static final String PROP_INIT_URLS_PATH2 = "shiro.ini.urls.path2";
这里附上读取并拼接两个 ini的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64private boolean loadIniPath1ANd2(Ini ini) { String urlsAll = ""; String urls1 = readConfig(ShiroEnvStarter.PROP_INIT_URLS_PATH1); String urls2 = readConfig(ShiroEnvStarter.PROP_INIT_URLS_PATH2); urlsAll = urls1 + urls2; if (!urlsAll.equals("")) { String iniUrls = "[urls]rn" + urlsAll; log.info("shiro ini urls ---> rn" + iniUrls); // Ini ini = new Ini(); // ini.load(iniUrls); // Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME); // Log.info(section.toString()); // 注意这个代码中这里load过一次了 ini.load(iniUrls); // 此处验证了 ini并没有全被覆盖,只覆盖了 加载的配置文件部分 // 如果新加载的内容中 只有 [main] 标签不会被覆盖,但是如果 [main]标签下有内容 则会覆盖之前的配置 // for (Entry<String, Ini.Section> entry : ini.entrySet()) { // jline.internal.Log.info(entry.getKey()); // for (Entry<String, String> entryStr : entry.getValue().entrySet()) { // jline.internal.Log.info(entryStr); // } // } return true; } return false; } private String readConfig(String confPath) { String urls1 = ""; try { String path = conf.get(confPath, "").trim(); log.info("path:" + path); if (path != null && appContext.getResourceLoader().has(path)) { InputStream is = ResourceUtils.getInputStreamForPath("classpath:" + path); if (is != null) { urls1 = readIniFile(is); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return urls1; } private String readIniFile(InputStream is) throws IOException { // InputStreamReader reader =new InputStreamReader(new // FileInputStream(file),"UTF-8"); InputStreamReader reader = new InputStreamReader(is); BufferedReader br = new BufferedReader(reader); StringBuffer sbf = new StringBuffer(); while (true) { String str = br.readLine(); if (str != null) { sbf.append(str).append("rn"); } else { break; } } br.close(); reader.close(); return sbf.toString(); }
当然代码中依旧有可以优化的地方,不过这里就先不写了,嘿嘿
不过至此已经达到能想到的最好的效果了,父子项目中 父项目配置 shiro main中验证和DB,Redis的大部分通用配置,以及所有通用的urls过滤,而子类可以添加新的urls配置,并且各个子项目中 shiro配置并不冲突.
至此整偏博客结束,如果其中有错误也请大家告诉我了~~
下面是源码部分,不看可以跳过了!~
四.源码部分
starter源码部分
不包括starter中未修改的类
ShiroEnvStarter.java
1
2
3
4
5
6
7//添加常量 @PropDoc(value = "urls过滤清单ini文件1路径") public static final String PROP_INIT_URLS_PATH1 = "shiro.ini.urls.path1"; @PropDoc(value = "urls过滤清单ini文件2路径") public static final String PROP_INIT_URLS_PATH2 = "shiro.ini.urls.path2";
NbShiroEnvironmentLoaderListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87//修改 import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import org.apache.shiro.ShiroException; import org.apache.shiro.config.ConfigurationException; import org.apache.shiro.util.ClassUtils; import org.apache.shiro.util.UnknownClassException; import org.apache.shiro.web.env.EnvironmentLoader; import org.apache.shiro.web.env.EnvironmentLoaderListener; import org.apache.shiro.web.env.IniWebEnvironment; import org.nutz.boot.AppContext; import org.nutz.ioc.impl.PropertiesProxy; import org.nutz.lang.Lang; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jline.internal.Log; public class NbShiroEnvironmentLoaderListener extends EnvironmentLoaderListener { private static final Logger log = LoggerFactory.getLogger(NbShiroEnvironmentLoaderListener.class); protected PropertiesProxy conf; protected AppContext appContext; @Override public void contextInitialized(ServletContextEvent sce) { PropertiesProxy conf = appContext.getConfigureLoader().get(); try { boolean hasUrlsPath = hasIniUrlsPath(conf, appContext); // 走原生API的shiro.ini文件吗? String iniPath = conf.get("shiro.ini.path", "shiro.ini"); boolean hasIniPath = conf.has("shiro.ini.path") || appContext.getResourceLoader().has(iniPath); if (hasIniPath || (hasIniPath && hasUrlsPath)) { sce.getServletContext().setAttribute(EnvironmentLoader.CONFIG_LOCATIONS_PARAM, iniPath); super.contextInitialized(sce); return; } } catch (Exception e) { throw Lang.wrapThrow(e); } // 没有配置文件 走nb(默认)配置 sce.getServletContext().setAttribute(ENVIRONMENT_CLASS_PARAM, NbResourceBasedWebEnvironment.class.getName()); super.contextInitialized(sce); } protected Class<?> determineWebEnvironmentClass(ServletContext servletContext) { // nb 默认配置 String className = servletContext.getInitParameter(ENVIRONMENT_CLASS_PARAM); if (className != null) { try { return ClassUtils.forName(className); } catch (UnknownClassException ex) { throw new ConfigurationException("Failed to load custom WebEnvironment class [" + className + "]", ex); } } else { try { boolean hasUrlsPath = hasIniUrlsPath(conf, appContext); // 如果有配置文件 String iniPath = conf.get("shiro.ini.path", "shiro.ini"); boolean hasIniPath = conf.has("shiro.ini.path") || appContext.getResourceLoader().has(iniPath); if (hasIniPath && hasUrlsPath) { return IniMixWebEnvironment.class; } else if (hasIniPath) { return IniWebEnvironment.class; } } catch (IOException e) { throw new ShiroException(e); } return NbResourceBasedWebEnvironment.class; } } private boolean hasIniUrlsPath(PropertiesProxy conf, AppContext appContext) throws IOException { String iniUrlsPath1 = conf.get(ShiroEnvStarter.PROP_INIT_URLS_PATH1, null); boolean hasIniUrlsPath1 = false; if (iniUrlsPath1 != null) { hasIniUrlsPath1 = (conf.has(ShiroEnvStarter.PROP_INIT_URLS_PATH1) || appContext.getResourceLoader().has(iniUrlsPath1)); } String iniUrlsPath2 = conf.get(ShiroEnvStarter.PROP_INIT_URLS_PATH2, null); boolean hasIniUrlsPath2 = false; if (iniUrlsPath2 != null) { hasIniUrlsPath2 = (conf.has(ShiroEnvStarter.PROP_INIT_URLS_PATH2) || appContext.getResourceLoader().has(iniUrlsPath2)); } if (hasIniUrlsPath1 || hasIniUrlsPath2) { return true; } return false; } }
基于 shiro原生实现的实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Map; import javax.servlet.ServletContext; import org.apache.shiro.config.ConfigurationException; import org.apache.shiro.config.Ini; import org.apache.shiro.config.IniFactorySupport; import org.apache.shiro.io.ResourceUtils; import org.apache.shiro.util.CollectionUtils; import org.apache.shiro.util.Destroyable; import org.apache.shiro.util.Initializable; import org.apache.shiro.util.StringUtils; import org.apache.shiro.web.config.IniFilterChainResolverFactory; import org.apache.shiro.web.config.WebIniSecurityManagerFactory; import org.apache.shiro.web.env.IniWebEnvironment; import org.apache.shiro.web.env.ResourceBasedWebEnvironment; import org.apache.shiro.web.env.WebEnvironment; import org.apache.shiro.web.filter.mgt.FilterChainResolver; import org.apache.shiro.web.mgt.WebSecurityManager; import org.apache.shiro.web.util.WebUtils; import org.nutz.boot.AppContext; import org.nutz.ioc.Ioc; import org.nutz.ioc.impl.PropertiesProxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link WebEnvironment} implementation configured by an {@link Ini} instance * or {@code Ini} resource locations. * * 代码主要实现部分由shiro IniWebEnvironment源码抄过来的 <br> * 修改了 createFilterChainResolver 方法,让 ini又load了一个 urls 配置 <br> * 目前从现象看 ini.load 似乎不会覆盖整个配置 * * @since 1.2 */ public class IniMixWebEnvironment extends ResourceBasedWebEnvironment implements Initializable, Destroyable { // *********非源码部分********** protected AppContext appContext; protected Ioc ioc; protected PropertiesProxy conf; // **************************** public static final String DEFAULT_WEB_INI_RESOURCE_PATH = "/WEB-INF/shiro.ini"; private static final Logger log = LoggerFactory.getLogger(IniWebEnvironment.class); /** * The Ini that configures this WebEnvironment instance. */ private Ini ini; /** * Initializes this instance by resolving any potential (explicit or * resource-configured) {@link Ini} configuration and calling * {@link #configure() configure} for actual instance configuration. */ public void init() { // *********非源码部分********** appContext = AppContext.getDefault(); ioc = appContext.getIoc(); conf = appContext.getConfigureLoader().get(); // **************************** Ini ini = getIni(); String[] configLocations = getConfigLocations(); if (log.isWarnEnabled() && !CollectionUtils.isEmpty(ini) && configLocations != null && configLocations.length > 0) { log.warn("Explicit INI instance has been provided, but configuration locations have also been " + "specified. The {} implementation does not currently support multiple Ini config, but this may " + "be supported in the future. Only the INI instance will be used for configuration.", IniWebEnvironment.class.getName()); } if (CollectionUtils.isEmpty(ini)) { log.debug("Checking any specified config locations."); ini = getSpecifiedIni(configLocations); } if (CollectionUtils.isEmpty(ini)) { log.debug("No INI instance or config locations specified. Trying default config locations."); ini = getDefaultIni(); } if (CollectionUtils.isEmpty(ini)) { String msg = "Shiro INI configuration was either not found or discovered to be empty/unconfigured."; throw new ConfigurationException(msg); } setIni(ini); configure(); } protected void configure() { this.objects.clear(); WebSecurityManager securityManager = createWebSecurityManager(); setWebSecurityManager(securityManager); FilterChainResolver resolver = createFilterChainResolver(); if (resolver != null) { setFilterChainResolver(resolver); } } protected Ini getSpecifiedIni(String[] configLocations) throws ConfigurationException { Ini ini = null; if (configLocations != null && configLocations.length > 0) { if (configLocations.length > 1) { log.warn( "More than one Shiro .ini config location has been specified. Only the first will be " + "used for configuration as the {} implementation does not currently support multiple " + "files. This may be supported in the future however.", IniWebEnvironment.class.getName()); } // required, as it is user specified: ini = createIni(configLocations[0], true); } return ini; } protected Ini getDefaultIni() { Ini ini = null; String[] configLocations = getDefaultConfigLocations(); if (configLocations != null) { for (String location : configLocations) { ini = createIni(location, false); if (!CollectionUtils.isEmpty(ini)) { log.debug("Discovered non-empty INI configuration at location '{}'. Using for configuration.", location); break; } } } return ini; } /** * Creates an {@link Ini} instance reflecting the specified path, or * {@code null} if the path does not exist and is not required. * <p/> * If the path is required and does not exist or is empty, a * {@link ConfigurationException} will be thrown. * * @param configLocation the resource path to load into an {@code Ini} instance. * @param required if the path must exist and be converted to a non-empty * {@link Ini} instance. * @return an {@link Ini} instance reflecting the specified path, or * {@code null} if the path does not exist and is not required. * @throws ConfigurationException if the path is required but results in a null * or empty Ini instance. */ protected Ini createIni(String configLocation, boolean required) throws ConfigurationException { Ini ini = null; if (configLocation != null) { ini = convertPathToIni(configLocation, required); } if (required && CollectionUtils.isEmpty(ini)) { String msg = "Required configuration location '" + configLocation + "' does not exist or did not " + "contain any INI configuration."; throw new ConfigurationException(msg); } return ini; } protected FilterChainResolver createFilterChainResolver() { FilterChainResolver resolver = null; Ini ini = getIni(); if (!CollectionUtils.isEmpty(ini)) { // only create a resolver if the 'filters' or 'urls' sections are defined: // Ini.Section urls = ini.getSection(IniFilterChainResolverFactory.URLS); // Ini.Section filters = ini.getSection(IniFilterChainResolverFactory.FILTERS); // *********非源码部分********** // boolean loadUrls = loadIniUrls(ini); boolean loadUrls = loadIniPath1ANd2(ini); if (loadUrls) { // **************************** // if (!CollectionUtils.isEmpty(urls) || !CollectionUtils.isEmpty(filters)) { // either the urls section or the filters section was defined. Go ahead and create the resolver: IniFilterChainResolverFactory factory = new IniFilterChainResolverFactory(ini, this.objects); resolver = factory.getInstance(); } } return resolver; } // *********非源码部分********** private boolean loadIniPath1ANd2(Ini ini) { String urlsAll = ""; String urls1 = readConfig(ShiroEnvStarter.PROP_INIT_URLS_PATH1); String urls2 = readConfig(ShiroEnvStarter.PROP_INIT_URLS_PATH2); urlsAll = urls1 + urls2; if (!urlsAll.equals("")) { String iniUrls = "[urls]rn" + urlsAll; log.info("shiro ini urls ---> rn" + iniUrls); // Ini ini = new Ini(); // ini.load(iniUrls); // Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME); // Log.info(section.toString()); ini.load(iniUrls); // 此处验证了 ini并没有全被覆盖,只覆盖了 加载的配置文件部分 // 如果新加载的内容中 只有 [main] 标签不会被覆盖,但是如果 [main]标签下有内容 则会覆盖之前的配置 // for (Entry<String, Ini.Section> entry : ini.entrySet()) { // jline.internal.Log.info(entry.getKey()); // for (Entry<String, String> entryStr : entry.getValue().entrySet()) { // jline.internal.Log.info(entryStr); // } // } return true; } return false; } private String readConfig(String confPath) { String urls1 = ""; try { String path = conf.get(confPath, "").trim(); log.info("path:" + path); if (path != null && appContext.getResourceLoader().has(path)) { InputStream is = ResourceUtils.getInputStreamForPath("classpath:" + path); if (is != null) { urls1 = readIniFile(is); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return urls1; } private String readIniFile(InputStream is) throws IOException { // InputStreamReader reader =new InputStreamReader(new // FileInputStream(file),"UTF-8"); InputStreamReader reader = new InputStreamReader(is); BufferedReader br = new BufferedReader(reader); StringBuffer sbf = new StringBuffer(); while (true) { String str = br.readLine(); if (str != null) { sbf.append(str).append("rn"); } else { break; } } br.close(); reader.close(); return sbf.toString(); } private boolean loadIniUrls(Ini ini) { // 使用了 原 start中定义的 shiro.ini.urls String config = conf.get(ShiroEnvStarter.PROP_INIT_URLS, "").trim(); if (config != null && !config.equals("")) { String iniUrls = "[urls]rn" + config; log.info("shiro ini urls ---> rn" + iniUrls); // Ini ini = new Ini(); // ini.load(iniUrls); // Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME); // Log.info(section.toString()); ini.load(iniUrls); return true; } return false; } // **************************** protected WebSecurityManager createWebSecurityManager() { WebIniSecurityManagerFactory factory; Ini ini = getIni(); if (CollectionUtils.isEmpty(ini)) { factory = new WebIniSecurityManagerFactory(); } else { factory = new WebIniSecurityManagerFactory(ini); } WebSecurityManager wsm = (WebSecurityManager) factory.getInstance(); // SHIRO-306 - get beans after they've been created (the call was before the // factory.getInstance() call, // which always returned null. Map<String, ?> beans = factory.getBeans(); if (!CollectionUtils.isEmpty(beans)) { this.objects.putAll(beans); } return wsm; } /** * Returns an array with two elements, {@code /WEB-INF/shiro.ini} and * {@code classpath:shiro.ini}. * * @return an array with two elements, {@code /WEB-INF/shiro.ini} and * {@code classpath:shiro.ini}. */ protected String[] getDefaultConfigLocations() { return new String[] { DEFAULT_WEB_INI_RESOURCE_PATH, IniFactorySupport.DEFAULT_INI_RESOURCE_PATH }; } /** * Converts the specified file path to an {@link Ini} instance. * <p/> * If the path does not have a resource prefix as defined by * {@link org.apache.shiro.io.ResourceUtils#hasResourcePrefix(String)}, the path * is expected to be resolvable by the {@code ServletContext} via * {@link javax.servlet.ServletContext#getResourceAsStream(String)}. * * @param path the path of the INI resource to load into an INI instance. * @param required if the specified path must exist * @return an INI instance populated based on the given INI resource path. */ private Ini convertPathToIni(String path, boolean required) { // TODO - this logic is ugly - it'd be ideal if we had a Resource API to // polymorphically encaspulate this behavior Ini ini = null; if (StringUtils.hasText(path)) { InputStream is = null; // SHIRO-178: Check for servlet context resource and not only resource paths: if (!ResourceUtils.hasResourcePrefix(path)) { is = getServletContextResourceStream(path); } else { try { is = ResourceUtils.getInputStreamForPath(path); } catch (IOException e) { if (required) { throw new ConfigurationException(e); } else { if (log.isDebugEnabled()) { log.debug("Unable to load optional path '" + path + "'.", e); } } } } if (is != null) { ini = new Ini(); ini.load(is); } else { if (required) { throw new ConfigurationException("Unable to load resource path '" + path + "'"); } } } return ini; } // TODO - this logic is ugly - it'd be ideal if we had a Resource API to // polymorphically encaspulate this behavior private InputStream getServletContextResourceStream(String path) { InputStream is = null; path = WebUtils.normalize(path); ServletContext sc = getServletContext(); if (sc != null) { is = sc.getResourceAsStream(path); } return is; } /** * Returns the {@code Ini} instance reflecting this WebEnvironment's * configuration. * * @return the {@code Ini} instance reflecting this WebEnvironment's * configuration. */ public Ini getIni() { return this.ini; } /** * Allows for configuration via a direct {@link Ini} instance instead of via * {@link #getConfigLocations() config locations}. * <p/> * If the specified instance is null or empty, the fallback/default * resource-based configuration will be used. * * @param ini the ini instance to use for creation. */ public void setIni(Ini ini) { this.ini = ini; } }
如果以后想到什么再补充吧
最后
以上就是内向画板最近收集整理的关于 在NutzBoot中拆分Shiro.ini配置文件使 Urls 可以配置多个并和 main 配置分离的全部内容,更多相关内容请搜索靠谱客的其他文章。
发表评论 取消回复