0%

issue
Spring MVC提交form表单后台通过@ModelAttribute获取参数为乱码
Spring MVC submit form and get random code parameters through `@ModelAttribute

Java Config WebInitializer

傻了,将CharacterEncodingFilter部分放到DispatcherServlet部分前面就可以了

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
public class WebInitializer implements WebApplicationInitializer {

@Override
public void onStartup(javax.servlet.ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ApplicationConfig.class);
sc.addListener(new ContextLoaderListener(rootContext));

//CharacterEncodingFilter
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
FilterRegistration filterRegistration =
sc.addFilter("characterEncodingFilter", characterEncodingFilter);
filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");//注意这里匹配 "/*"

//follow can be deleted
//sc.addFilter("hibernateFilter", OpenSessionInViewFilter.class).addMappingForUrlPatterns(null, false, "/*");

//maybe follow will be use
// sc.addFilter("OpenEntityManagerInViewFilter", org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.class).addMappingForUrlPatterns(null, false, "/*");

//springmvc上下文
AnnotationConfigWebApplicationContext springMvcContext = new AnnotationConfigWebApplicationContext();
springMvcContext.register(MvcConfig.class);

//DispatcherServlet
DispatcherServlet dispatcherServlet = new DispatcherServlet(springMvcContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
ServletRegistration.Dynamic dynamic = sc.addServlet("dispatcherServlet", dispatcherServlet);
dynamic.setLoadOnStartup(1);
dynamic.addMapping("/");


}
}

SQL and QL injection can be effectively prevented with the use of JPA Named Queries. In the contrary to the CMP 2.X spec, JPA QL are in general more flexible and can be parameterized.

You can cover almost 90% of all cases with named queries. However, named queries only works in case the structure of the query is stable, and the parameters vary.

Sometimes more flexibility is needed. Building the queries with Strings has several drawbacks:

Lack or IDE support
Syntax is evaluated at runtime. (affects performance and stability)
QL/SQL injection is possible.
With a little “hack” and builder pattern, it is possible to use almost the old syntax more conveniently.

Instead of writing a something like this:

1
String expected = "SELECT e FROM Customer e WHERE e.name = :name";

You could chain methods, which looks like this:

1
EntityQuery query = new EntityQuery.SELECT().ENTITY().FROM(Customer.class).WHERE().attribute("name").build();

A static inner class with the name SELECT implements the builder pattern and takes the responsibility for building the queries:

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
public class EntityQuery {

private String query;
//attribute declaration
public static class SELECT<T>{

public SELECT(){
this.sqlQuery = new StringBuilder();
this.sqlQuery.append("SELECT");
}

public SELECT column(String name){
if(!multipleColumns) {
multipleColumns = true;
}else{
this.sqlQuery.append(SEPARATOR);
}
this.sqlQuery.append(name);
return this;
}

public SELECT FROM(Class entity){
this.sqlQuery.append(BLANK).append(FROM).append(BLANK);
}
}
}

The Entity Query Builder, as well as the unit tests are available from http://qlb.dev.java.net. I’m working now on the EntityManager integration. First samples should be available in few days.

微信分享占位ICON(如有侵权联系删除)

——————–华丽丽的分割线————————

I miss you.

(づ。◕‿‿◕。)づ 外面浪了一天,好累,我想静静,内容待补充…… 2016年2月14日01:46:12

update:然后就没然后了,反正我也不记得了,laudukang,2017-11-25 22:39:39

T findOne(ID id)

Retrieves an entity by its id.
Parameters:
id - must not be null.
Returns:
the entity with the given id or null if none found
Throws:
IllegalArgumentException - if id is null

T getOne(ID id)

Returns a reference to the entity with the given identifier.
Parameters:
id - must not be null.
Returns:
a reference to the entity with the given identifier.
See Also:
EntityManager.getReference(Class, Object)

{ % ossimag os-admin-debug.png % }
DEBUG下:osAdmin 为getOne()查询的结果,osAdmin2为findOne查询的结果

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property saveAdmin found for type OsAdmin!

Exception message:

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
java.lang.IllegalStateException: Failed to load ApplicationContext

at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: me.laudukang.persistence.repository.AdminRepository me.laudukang.persistence.service.impl.AdminService.adminRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property saveAdmin found for type OsAdmin!
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 28 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: me.laudukang.persistence.repository.AdminRepository me.laudukang.persistence.service.impl.AdminService.adminRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property saveAdmin found for type OsAdmin!
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 42 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property saveAdmin found for type OsAdmin!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 44 more
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property saveAdmin found for type OsAdmin!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:235)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:353)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:84)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:61)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:206)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:73)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:416)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:206)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 54 more

Solution:

  • YourInterfaceName
  • YourInterfaceNameCustom
  • YourInterfaceNameImpl
AdminRepositoryCustom.png

在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改 .gitignore 文件的方法。

这个文件每一行保存了一个匹配的规则例如:

1
2
3
4
5
6
7
#此为注释 – 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
*.pyc #这样设置了以后 所有的 .pyc 文件都不会添加到版本库中去。

另外 git 提供了一个全局的.gitignore,你可以在你的用户目录下创建~/.gitignoreglobal文件,以同样的规则来划定哪些文件是不需要版本控制的。
需要执行以下命令来使得它生效。

1
git config --global core.excludesfile ~/.gitignoreglobal

其他的一些过滤条件

1
2
3
4
5
6
* ?:代表任意的一个字符
* *:代表任意数目的字符
* {!ab}:必须不是此类型
* {ab,bb,cx}:代表ab,bb,cx中任一类型即可
* [abc]:代表a,b,c中任一字符即可
* [ ^abc]:代表必须不是a,b,c中任一字符

由于git不会加入空目录,所以下面做法会导致tmp不会存在

1
tmp/* //忽略tmp文件夹所有文件

改下方法,在tmp下也加一个.gitignore,内容为

1
2
*
!.gitignore

还有一种情况,就是已经commit了,再加入gitignore是无效的,所以需要删除下缓存

1
git rm -rf --cached ignore_file

.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。

另外 git 还提供了另一种 exclude 的方式来做同样的事情,不同的是 .gitignore 这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。而.git/info/exclude这里设置的则是你自己本地需要排除的文件。

他不会影响到其他人。也不会提交到版本库中去。

.gitignore 还有个有意思的小功能, 一个空的 .gitignore 文件 可以当作是一个 placeholder 。当你需要为项目创建一个空的 log 目录时, 这就变的很有用。 你可以创建一个 log 目录 在里面放置一个空的 .gitignore 文件。这样当你 clone 这个 repo 的时候 git 会自动的创建好一个空的 log 目录了。

reference:

Few months ago I started playing with Spring Framework, which I really enjoy. Looking for the tutorials I found some really great resources on the web as well as books. Unfortunately many of them were written for Spring 2.x, which lacks some recent features, mainly ability to configure everything by Java annotations (a.k.a. JavaConfig) rather than XML. That was something that kept me away from Spring at the first place - doing it programmatically gives much more sense of control and is more readable. So, that’s what I’m trying to achieve here, I’ll try to show you how to do it in more ‘modern’ way, showing integrations with various software packages along the way.
Let’s start with a simple skeleton Spring MVC application. Since version 3.1 it has Servlet 3 API support, I won’t use web.xml for configuring DispatcherServlet, rather I’ll configure it programmatically.

Full source code for this article is here on GitHub

Maven configuration

Most important dependencies for this project will be spring-webmvc, which provides DispatcherServlet and pulls other Spring artifacts together with it and Servlet 3.0 API.

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>

Initializer

AppInitializer is a class that implements WebApplicationInitializer interface. We hook up to onStartup() method, to add DispatcherServlet to ServletContext.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class AppInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}

private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("eu.kielczewski.example.config");
return context;
}

}

Several things happen here:

  • AnnotationConfigWebApplicationContext is created. It’s WebApplicationContext implementation that looks for Spring configuration in classes annotated with @Configuration annotation. setConfigLocation() method gets hint in which package(s) to look for them.
  • ContextLoaderListener is added to ServletContext – the purpose of this is to ‘glue’ WebApplicationContext to the lifecycle of ServletContext.
  • DispatcherServlet is created and initialized with WebApplicationContext we have created, and it’s mapped to “/*“ URLs and set to eagerly load on application startup.

Configuration classes

The main AppConfig configuration class doesn’t do anything but hits Spring on where to look for its components through @ComponentScan annotation.

1
2
3
4
@Configuration
@ComponentScan(basePackages = "eu.kielczewski.example")
public class AppConfig {
}

WebMvcConfig class enables Spring MVC with @EnableWebMvc annotation. It extends WebMvcConfigurerAdapter, which provides empty methods that can be overridden to customize default configuration of Spring MVC. We will stick to default configuration at this time, but it’s advised for you to see what the possibilities are.

1
2
3
4
@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
}

Controller

Controllers are annotated with @Controller. It is found by Spring because of @ComponentScan annotation in AppConfig. The method will intercept GET request to “/“ to which the response will be sent. @ResponseBody indicates that whatever this method returns will be response body, and in this case it’s just a “Hello world” String.

1
2
3
4
5
6
7
8
9
10
@Controller
public class IndexController {

@RequestMapping(value = "/", method = RequestMethod.GET)
@ResponseBody
public String showIndex() {
return "Hello world";
}

}

Summary

That is all that is needed for skeleton Spring MVC application written using pure JavaConfig and for Servlet 3 API, without web.xml.

See the working example you can play around with - https://github.com/bkielczewski/example-spring-mvc-initializer

reference:

7.1.2
谷歌又玩我23333

自7.1.2(开始?),”captive_portal_detection_enabled”设置已被废弃,现在改为了”captive_portal_mode”选项,该选项可设置为以下3种值:

0:彻底禁用检测(Don’t attempt to detect captive portals.)
1:检测到需要登录则弹窗提醒(默认值)(When detecting a captive portal, display a notification that prompts the user to sign in.)
2:检测到需要登录则自动断开此热点并不再自动连接(When detecting a captive portal, immediately disconnect from the network and do not reconnect to that network in the future.)
叹号杀手已经更新以支持该版本。

但愿以后谷歌不要再乱改了233333

感谢 jingyu9575 的帮助 https://github.com/Noisyfox/NoExclamation/issues/2

7.1.1
从7.1.1开始,检测用的服务器地址储存格式发生了变化,改为了:

1
2
3
private static String getCaptivePortalServerHttpsUrl(Context context) {
return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL);
}

以及

1
2
3
public static String getCaptivePortalServerHttpUrl(Context context) {
return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
}

可以看到,系统不会自动加入”generate_204″的后缀了,这意味着url可以设计的更加灵活,同时也意味着在设置的时候需要填入完整的url:

1
adb shell "settings put global captive_portal_https_url https://www.noisyfox.cn/generate_204"

当然如果只有http的话,可以执行:

1
2
adb shell "settings put global captive_portal_use_https 0"
adb shell "settings put global captive_portal_http_url http://www.noisyfox.cn/generate_204"

原文:关于 ANDROID 5.0-7.1.2 网络图标上的感叹号及其解决办法