2017年9月29日金曜日
仮想通貨採掘スクリプトでThe Pirate Bayが得る収入は?
TPBが使用したのは仮想通貨「Monero(XMR)」を採掘するCoinhiveのスクリプトだ。TorrentFreakの記事作成時点で、支払われるMoneroは100万(1M)ハッシュ当たり0.00015XMRだったという。CoinhiveのWebサイトによれば、採掘スクリプトはネイティブの採掘プログラムの65%程度のパフォーマンスとのことで、デスクトップ版のCore i7で1秒当たり90ハッシュ(90 h/s)と説明されている。TorrentFreakがCoinhiveに問い合わせたところ、ミッドレンジのノートPCで30 h/sとの回答を得たそうだ。TPBの訪問件数についてはSimilarWebのデータを用い、月間約3億1,500万件(315M件)。訪問1回あたりの滞在時間は平均5分としている。
これらのデータから1か月に生成できるハッシュは、30ハッシュ×300秒×315M件で2,835,000Mハッシュとなる。ただし、TPBでは適切なCPU使用率を20〜30%としており、30%の場合で850,500Mハッシュまで減少する。1Mハッシュ当たり0.00015XMRが支払われるとすれば、TPBの1か月の収入は約127.5XMR。試算時のレートではおよそ12,000ドルになったとのこと。Adblock Plusが説明するような方法で採掘スクリプトをブロックする人もいるため、実際の収入はさらに少なくなるとみられる。仮想通貨採掘スクリプトはWeb広告に代わる存在になりえるのだろうか。
2017年9月26日火曜日
Spring mvc+Mybatis的整合
・ pom文件的配置
・ applicationContext.xml配置
・ 通用mapper与分页插件配置
・ cache配置
・ spring-mvc.xml的配置
・ applicationContext-shiro.xml配置
・ properties文件
・ 集成
・ 测试
一.项目的集成,各种配置文件整理
1. pom文件的配置 废话不多说 贴代码
2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4. <modelVersion>4.0.0</modelVersion>
5. <groupId>com.mark.mession</groupId>
6. <artifactId>xfMession</artifactId>
7. <packaging>war</packaging>
8. <version>1.0-SNAPSHOT</version>
9. <name>xfMession Maven Webapp</name>
10. <url>http://maven.apache.org</url>
11. <properties>
12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13. <!-- MyBatis Generator -->
14. <!-- Java接口和实体类 -->
15. <targetJavaProject>${basedir}/src/main/java</targetJavaProject>
16. <targetMapperPackage>com.marks.framework.dao</targetMapperPackage>
17. <targetModelPackage>com.marks.framework.entity</targetModelPackage>
18. <!-- XML生成路径 -->
19. <targetResourcesProject>${basedir}/src/main/resources</targetResourcesProject>
20. <targetXMLPackage>mapper</targetXMLPackage>
21. <!-- 编译jdk版本 -->
22. <jdk.version>1.8</jdk.version>
23. <!-- 依赖版本 -->
24. <slf4j.version>1.6.6</slf4j.version>
25. <log4j.version>1.2.12</log4j.version>
26. <mybatis.version>3.3.1</mybatis.version>
27. <mapper.version>3.3.6</mapper.version>
28. <pagehelper.version>4.1.4</pagehelper.version>
29. <mysql.version>5.1.29</mysql.version>
30. <shiro.version>1.2.3</shiro.version>
31. <aspectj.version>1.6.12</aspectj.version>
32. <spring.version>4.1.2.RELEASE</spring.version>
33. <mybatis.spring.version>1.2.4</mybatis.spring.version>
34. </properties>
35.
36. <dependencies>
37. <dependency>
38. <groupId>junit</groupId>
39. <artifactId>junit</artifactId>
40. <version>4.11</version>
41. <scope>test</scope>
42. </dependency>
43. <!-- log start -->
44. <dependency>
45. <groupId>log4j</groupId>
46. <artifactId>log4j</artifactId>
47. <version>${log4j.version}</version>
48. </dependency>
49. <dependency>
50. <groupId>org.slf4j</groupId>
51. <artifactId>slf4j-api</artifactId>
52. <version>${slf4j.version}</version>
53. </dependency>
54. <dependency>
55. <groupId>org.slf4j</groupId>
56. <artifactId>slf4j-log4j12</artifactId>
57. <version>${slf4j.version}</version>
58. <exclusions>
59. <exclusion>
60. <artifactId>log4j</artifactId>
61. <groupId>log4j</groupId>
62. </exclusion>
63. </exclusions>
64. </dependency>
65. <!-- log end -->
66.
67. <!--web-->
68. <dependency>
69. <groupId>javax.servlet</groupId>
70. <artifactId>servlet-api</artifactId>
71. <version>2.5</version>
72. <scope>provided</scope>
73. </dependency>
74. <dependency>
75. <groupId>javax.servlet.jsp</groupId>
76. <artifactId>jsp-api</artifactId>
77. <version>2.1</version>
78. <scope>provided</scope>
79. </dependency>
80. <dependency>
81. <groupId>javax.servlet</groupId>
82. <artifactId>jstl</artifactId>
83. <version>1.2</version>
84. </dependency>
85. <dependency>
86. <groupId>javax.ws.rs</groupId>
87. <artifactId>javax.ws.rs-api</artifactId>
88. <version>2.0</version>
89. </dependency>
90. <dependency>
91. <groupId>javax.websocket</groupId>
92. <artifactId>javax.websocket-api</artifactId>
93. <version>1.0</version>
94. </dependency>
95. <dependency>
96. <groupId>javax.annotation</groupId>
97. <artifactId>javax.annotation-api</artifactId>
98. <version>1.2</version>
99. </dependency>
100. <dependency>
101. <groupId>javax.transaction</groupId>
102. <artifactId>javax.transaction-api</artifactId>
103. <version>1.2</version>
104. </dependency>
105.
106. <!--Spring-->
107. <dependency>
108. <groupId>org.springframework</groupId>
109. <artifactId>spring-context</artifactId>
110. <exclusions>
111. <exclusion>
112. <artifactId>commons-logging</artifactId>
113. <groupId>commons-logging</groupId>
114. </exclusion>
115. </exclusions>
116. </dependency>
117. <dependency>
118. <groupId>org.springframework</groupId>
119. <artifactId>spring-orm</artifactId>
120. </dependency>
121. <dependency>
122. <groupId>org.springframework</groupId>
123. <artifactId>spring-oxm</artifactId>
124. </dependency>
125. <dependency>
126. <groupId>org.springframework</groupId>
127. <artifactId>spring-jdbc</artifactId>
128. </dependency>
129. <dependency>
130. <groupId>org.springframework</groupId>
131. <artifactId>spring-tx</artifactId>
132. </dependency>
133. <dependency>
134. <groupId>org.springframework</groupId>
135. <artifactId>spring-web</artifactId>
136. </dependency>
137. <dependency>
138. <groupId>org.springframework</groupId>
139. <artifactId>spring-webmvc</artifactId>
140. </dependency>
141. <dependency>
142. <groupId>org.springframework</groupId>
143. <artifactId>spring-aop</artifactId>
144. </dependency>
145. <dependency>
146. <groupId>org.springframework</groupId>
147. <artifactId>spring-test</artifactId>
148. </dependency>
149.
150. <dependency>
151. <groupId>org.springframework</groupId>
152. <artifactId>spring-context-support</artifactId>
153. <version>${spring.version}</version>
154. </dependency>
155.
156.
157.
158. <!-- shiro -->
159. <dependency>
160. <groupId>org.apache.shiro</groupId>
161. <artifactId>shiro-spring</artifactId>
162. <version>${shiro.version}</version>
163. </dependency>
164. <dependency>
165. <groupId>org.apache.shiro</groupId>
166. <artifactId>shiro-ehcache</artifactId>
167. <version>${shiro.version}</version>
168. <exclusions>
169. <exclusion>
170. <artifactId>ehcache-core</artifactId>
171. <groupId>net.sf.ehcache</groupId>
172. </exclusion>
173. </exclusions>
174. </dependency>
175. <dependency>
176. <groupId>org.apache.shiro</groupId>
177. <artifactId>shiro-core</artifactId>
178. <version>${shiro.version}</version>
179. <exclusions>
180. <exclusion>
181. <artifactId>slf4j-api</artifactId>
182. <groupId>org.slf4j</groupId>
183. </exclusion>
184. </exclusions>
185. </dependency>
186. <dependency>
187. <groupId>org.apache.shiro</groupId>
188. <artifactId>shiro-web</artifactId>
189. <version>${shiro.version}</version>
190. </dependency>
191. <dependency>
192. <groupId>org.apache.shiro</groupId>
193. <artifactId>shiro-quartz</artifactId>
194. <version>${shiro.version}</version>
195. </dependency>
196.
197. <!-- aspectjweaver -->
198. <dependency>
199. <groupId>org.aspectj</groupId>
200. <artifactId>aspectjweaver</artifactId>
201. <version>${aspectj.version}</version>
202. </dependency>
203. <dependency>
204. <groupId>org.aspectj</groupId>
205. <artifactId>aspectjrt</artifactId>
206. <version>${aspectj.version}</version>
207. </dependency>
208.
209.
210. <!--spring-oxm依赖-->
211. <dependency>
212. <groupId>org.codehaus.castor</groupId>
213. <artifactId>castor-xml</artifactId>
214. <version>1.3.3</version>
215. </dependency>
216. <!--spring-json依赖-->
217. <dependency>
218. <groupId>com.fasterxml.jackson.core</groupId>
219. <artifactId>jackson-databind</artifactId>
220. <version>2.4.2</version>
221. </dependency>
222. <dependency>
223. <groupId>com.fasterxml.jackson.dataformat</groupId>
224. <artifactId>jackson-dataformat-xml</artifactId>
225. <version>2.4.2</version>
226. </dependency>
227. <!--spring-aop依赖-->
228. <dependency>
229. <groupId>org.aspectj</groupId>
230. <artifactId>aspectjweaver</artifactId>
231. <version>1.8.8</version>
232. </dependency>
233.
234. <!--上传文件-->
235. <dependency>
236. <groupId>commons-fileupload</groupId>
237. <artifactId>commons-fileupload</artifactId>
238. <version>1.3.1</version>
239. </dependency>
240.
241. <!--mysql-->
242. <dependency>
243. <groupId>mysql</groupId>
244. <artifactId>mysql-connector-java</artifactId>
245. <version>${mysql.version}</version>
246. </dependency>
247. <!--druid-->
248. <dependency>
249. <groupId>com.alibaba</groupId>
250. <artifactId>druid</artifactId>
251. <version>1.0.11</version>
252. </dependency>
253.
254. <!--Mybatis-->
255. <dependency>
256. <groupId>org.mybatis</groupId>
257. <artifactId>mybatis</artifactId>
258. <version>${mybatis.version}</version>
259. </dependency>
260. <dependency>
261. <groupId>org.mybatis</groupId>
262. <artifactId>mybatis-spring</artifactId>
263. <version>${mybatis.spring.version}</version>
264. </dependency>
265. <!-- Mybatis Generator -->
266. <dependency>
267. <groupId>org.mybatis.generator</groupId>
268. <artifactId>mybatis-generator-core</artifactId>
269. <version>1.3.2</version>
270. <scope>compile</scope>
271. <optional>true</optional>
272. </dependency>
273. <!--分页插件-->
274. <dependency>
275. <groupId>com.github.pagehelper</groupId>
276. <artifactId>pagehelper</artifactId>
277. <version>${pagehelper.version}</version>
278. </dependency>
279. <!--通用Mapper-->
280. <dependency>
281. <groupId>tk.mybatis</groupId>
282. <artifactId>mapper</artifactId>
283. <version>${mapper.version}</version>
284. </dependency>
285.
286. <dependency>
287. <groupId>net.sf.ehcache</groupId>
288. <artifactId>ehcache</artifactId>
289. <version>2.10.1</version>
290. <exclusions>
291. <exclusion>
292. <artifactId>slf4j-api</artifactId>
293. <groupId>org.slf4j</groupId>
294. </exclusion>
295. </exclusions>
296. </dependency>
297.
298.
299. <dependency>
300. <groupId>com.googlecode.ehcache-spring-annotations</groupId>
301. <artifactId>ehcache-spring-annotations</artifactId>
302. <version>1.2.0</version>
303. <exclusions>
304. <exclusion>
305. <artifactId>slf4j-api</artifactId>
306. <groupId>org.slf4j</groupId>
307. </exclusion>
308. </exclusions>
309. </dependency>
310.
311.
312. </dependencies>
313. <dependencyManagement>
314. <dependencies>
315. <dependency>
316. <groupId>org.springframework</groupId>
317. <artifactId>spring-framework-bom</artifactId>
318. <version>${spring.version}</version>
319. <type>pom</type>
320. <scope>import</scope>
321. </dependency>
322. </dependencies>
323. </dependencyManagement>
324. <repositories>
325. <repository>
326. <id>nexus</id>
327. <name>local private nexus</name>
328. <url>http://maven.oschina.net/content/groups/public/</url>
329. <releases>
330. <enabled>true</enabled>
331. </releases>
332. <snapshots>
333. <enabled>false</enabled>
334. </snapshots>
335. </repository>
336. <repository>
337. <id>sonatype-nexus-releases</id>
338. <name>Sonatype Nexus Releases</name>
339. <url>http://oss.sonatype.org/content/repositories/releases</url>
340. <releases>
341. <enabled>true</enabled>
342. </releases>
343. <snapshots>
344. <enabled>false</enabled>
345. </snapshots>
346. </repository>
347. <repository>
348. <id>sonatype-nexus-snapshots</id>
349. <name>Sonatype Nexus Snapshots</name>
350. <url>http://oss.sonatype.org/content/repositories/snapshots</url>
351. <releases>
352. <enabled>false</enabled>
353. </releases>
354. <snapshots>
355. <enabled>true</enabled>
356. </snapshots>
357. </repository>
358. </repositories>
359. <build>
360. <resources>
361. <resource>
362. <directory>${basedir}/src/main/java</directory>
363. <includes>
364. <include>**/*.xml</include>
365. </includes>
366. </resource>
367. <resource>
368. <directory>${basedir}/src/main/resources</directory>
369. </resource>
370. </resources>
371. <plugins>
372. <plugin>
373. <artifactId>maven-compiler-plugin</artifactId>
374. <configuration>
375. <source>${jdk.version}</source>
376. <target>${jdk.version}</target>
377. </configuration>
378. </plugin>
379. <plugin>
380. <groupId>org.mybatis.generator</groupId>
381. <artifactId>mybatis-generator-maven-plugin</artifactId>
382. <version>1.3.2</version>
383. <configuration>
384. <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
385. <overwrite>true</overwrite>
386. <verbose>true</verbose>
387. </configuration>
388. <dependencies>
389. <dependency>
390. <groupId>mysql</groupId>
391. <artifactId>mysql-connector-java</artifactId>
392. <version>${mysql.version}</version>
393. </dependency>
394. <dependency>
395. <groupId>tk.mybatis</groupId>
396. <artifactId>mapper</artifactId>
397. <version>${mapper.version}</version>
398. </dependency>
399. </dependencies>
400. </plugin>
401. </plugins>
402. </build>
</project>
2.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--spring的注解扫描 这里需要注意 有的时候报创建bean失败可能是这里扫描不到你所使用的注解标记的bean-->
<context:component-scan base-package="com.marks.framework.*"/>
<context:property-placeholder location="classpath:config/jdbc.properties"/>
<!-- Cache配置 -->
<cache:annotation-driven cache-manager="cacheManager"/>
<bean id="ehCacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml"/>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehCacheManagerFactory"/>
<!--配置alibaba druid 即DataSource-->
<!--对于druid的介绍可以参考 http://blog.csdn.net/qq892618896/article/details/52021642 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${ds.initialSize}"/>
<property name="minIdle" value="${ds.minIdle}"/>
<property name="maxActive" value="${ds.maxActive}"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${ds.maxWait}"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${ds.timeBetweenEvictionRunsMillis}"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${ds.minEvictableIdleTimeMillis}"/>
<property name="validationQuery" value="SELECT 'x'"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="false"/>
<property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="stat,log4j"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations">
<array>
<value>classpath:mapper/*.xml</value>
</array>
</property>
<property name="typeAliasesPackage" value="com.marks.framework.entity"/>
<!--分页插件的介绍请参考 https://github.com/pagehelper/Mybatis-PageHelper-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<!-- 这里的几个配置主要演示如何使用,如果不理解,一定要去掉下面的配置 -->
<property name="properties">
<value>
dialect=mysql
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<!--详细参数请参考 http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/2.Integration.md -->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.marks.framework.dao"/>
<!--默认mappers不配置会自动扫描mapper这个通用的-->
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!-- 对dataSource 数据源进行事务管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<!-- 事务管理 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 对insert,update,delete 开头的方法进行事务管理,只要有异常就回滚 -->
<tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<!-- select,count开头的方法,开启只读,提高数据库访问性能 -->
<tx:method name="select*" read-only="true"/>
<tx:method name="count*" read-only="true"/>
<!-- 对其他方法 使用默认的事务管理 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 事务 aop 配置 -->
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* com.marks.framework.service..*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
<!-- 配置使Spring采用CGLIB代理 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 启用对事务注解的支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
3.spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.marks.framework.controller"></context:component-scan>
<!--RequestMappingHandlerAdapter-->
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="stringHttpMessageConverter"/>
<ref bean="marshallingHttpMessageConverter"/>
<ref bean="mappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean id="marshallingHttpMessageConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="castorMarshaller"/>
<property name="unmarshaller" ref="castorMarshaller"/>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>application/xml;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>text/xml;charset=UTF-8</value>
</list>
</property>
</bean>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
<!--信息转化结束-->
<bean id="contentNegotiationManagerFactoryBean"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="text/html"/>
<property name="ignoreAcceptHeader" value="true"/>
<property name="favorPathExtension" value="true"/>
<property name="favorParameter" value="false"/>
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
</bean>
<!--内容协商-->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="text/html"/>
<property name="mediaTypes">
<map>
<entry key="json" value="application/json"/>
<entry key="xml" value="application/xml"/>
<entry key="html" value="text/html"/>
</map>
</property>
</bean>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller" ref="castorMarshaller"/>
</bean>
</list>
</property>
</bean>
<!-- 配置springMVC处理上传文件的信息 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<property name="maxUploadSize" value="10485760000"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
<!-- 启用shrio授权注解拦截方式 -->
<aop:config proxy-target-class="true"></aop:config>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
</beans>
4.applicationContext-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<description>apache shiro配置</description>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/rest/page/login"/>
<property name="successUrl" value="/rest/index"/>
<property name="unauthorizedUrl" value="/rest/page/401"/>
<property name="filterChainDefinitions">
<value>
<!-- 静态资源允许访问 -->
/static/** = anon
/assets/** = anon
<!-- 登录页允许访问 -->
/rest/user/login = anon
/rest/test2 = anon
/rest/page/select = anon
<!-- 其他资源需要认证 -->
/** = authc
</value>
</property>
</bean>
<!-- 缓存管理器 使用Ehcache实现 -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
</bean>
<!-- 会话DAO -->
<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"/>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO"/>
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realms">
<list>
<ref bean="securityRealm"/>
</list>
</property>
<!--cacheManager,集合spring缓存工厂 -->
<!--<property name="cacheManager" ref="shiroEhcacheManager" />-->
<!--<property name="sessionManager" ref="sessionManager" />-->
</bean>
<!-- Shiro生命周期处理器 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>
6.jdbc.properties
##JDBC Global Setting
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/tagmaps?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
##DataSource Global Setting
#配置初始化大小、最小、最大
ds.initialSize=1
ds.minIdle=1
ds.maxActive=20
#配置获取连接等待超时的时间
ds.maxWait=60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
ds.timeBetweenEvictionRunsMillis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
ds.minEvictableIdleTimeMillis=300000
# generator.xm连接配置
mapper.plugin = tk.mybatis.mapper.generator.MapperPlugin
mapper.Mapper = tk.mybatis.mapper.common.Mapper
7.log4j.properties
# DEBUG,INFO,WARN,ERROR,FATAL
LOG_LEVEL=info
log4j.rootLogger=${LOG_LEVEL},CONSOLE,FILE,E
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Encoding=utf-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
#log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss} %C{8}@(%F:%L):%m%n
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss} %C{1}@(%F:%L):%m%n
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.FILE.File=/Users/apple/Desktop/logs/mylogs.log
log4j.appender.FILE.Encoding=utf-8
log4j.appender.FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
#log4j.appender.FILE.layout=org.apache.log4j.HTMLLayout
log4j.appender.FILE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH\:mm\:ss} %C{8}@(%F\:%L)\:%m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =/Users/apple/Desktop/logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
8.ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="txswx-ehcache">
<diskStore path="java.io.tmpdir"/>
<!-- DefaultCache setting. -->
<defaultCache maxEntriesLocalHeap="10000" eternal="true" timeToIdleSeconds="300" timeToLiveSeconds="600"
overflowToDisk="true" maxEntriesLocalDisk="100000"/>
<cache name="testCache" eternal="false" maxElementsInMemory="100"
overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU" />
</ehcache>
9.ehcache-shiro.xml
<ehcache updateCheck="false" name="shiroCache">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>
10.generator.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="config/jdbc.properties"/>
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<plugin type="${mapper.plugin}">
<property name="mappers" value="${mapper.Mapper}"/>
</plugin>
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
</jdbcConnection>
<javaModelGenerator targetPackage="${targetModelPackage}" targetProject="${targetJavaProject}"/>
<sqlMapGenerator targetPackage="${targetXMLPackage}" targetProject="${targetResourcesProject}"/>
<javaClientGenerator targetPackage="${targetMapperPackage}" targetProject="${targetJavaProject}" type="XMLMAPPER" />
<table tableName="%" >
<generatedKey column="id" sqlStatement="Mysql" identity="true"/>
</table>
</context>
</generatorConfiguration>
二.集成开发
1.开发工具采用的是idea,数据库mysql 这里推荐navicat与mamp两款。
三.测试
废话完了,那么就得来点实际的,接下来演示项目的缓存与shiro的用法部分吧。
1.首先是cache。
controller
package com.marks.framework.controller;
import com.github.pagehelper.PageInfo;
import com.marks.framework.service.TagMapService;
import com.marks.framework.service.TestTagService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* Created 16/9/28 下午6:02
*
* @memo
*/
@Controller
public class TestApi {
Logger logger = Logger.getLogger(TestApi.class);
@Autowired
private TagMapService tagMapService;
@Autowired
private TestTagService testTagService;
@ResponseBody
@RequestMapping("/test1")
public List showTest() {
long start = System.currentTimeMillis();
List list = tagMapService.selectAll();
logger.error("所用的时间为:"+(System.currentTimeMillis()-start));
return list;
}
@ResponseBody
@RequestMapping("/test2")
public PageInfo showTest2() {
return testTagService.selectPageInfo(1,10);
}
}
service
package com.marks.framework.service;
import com.marks.framework.dao.MapTagMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created 16/9/28 下午5:59
*
* @memo
*/
@Service
public class TagMapService {
@Autowired
private MapTagMapper mapTagMapper;
public List selectAll() {
List list = mapTagMapper.selectAll();
return list;
}
}
不使用缓存注解 测试查询 结果为:
2016-09-29 10:03:00 [ http-nio-8033-exec-1:12176 ] - [ ERROR ] 所用的时间为:223
2016-09-29 10:06:13 [ http-nio-8033-exec-3:204667 ] - [ ERROR ] 所用的时间为:69
2016-09-29 10:06:36 [ http-nio-8033-exec-2:228363 ] - [ ERROR ] 所用的时间为:39
2016-09-29 10:07:02 [ http-nio-8033-exec-4:253452 ] - [ ERROR ] 所用的时间为:26
2016-09-29 10:07:36 [ http-nio-8033-exec-5:287906 ] - [ ERROR ] 所用的时间为:19
2016-09-29 10:08:06 [ http-nio-8033-exec-6:318311 ] - [ ERROR ] 所用的时间为:22
2016-09-29 10:08:30 [ http-nio-8033-exec-7:342038 ] - [ ERROR ] 所用的时间为:23
在service层增加一个注解
ackage com.marks.framework.service;
import com.marks.framework.dao.MapTagMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created 16/9/28 下午5:59
*
* @memo
*/
@Service
public class TagMapService {
@Autowired
private MapTagMapper mapTagMapper;
//这个testCache即是在ehcache.xml里面配置的
@Cacheable("testCache")
public List selectAll() {
List list = mapTagMapper.selectAll();
return list;
}
}
使用注解后测试结果为:
[ERROR] 2016-09-29 10:15:26 TestApi@(TestApi.java:35):所用的时间为:219
[ERROR] 2016-09-29 10:15:33 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:15:37 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:15:42 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:15:49 TestApi@(TestApi.java:35):所用的时间为:0
新增一个插入数据 刷新缓存
service
package com.marks.framework.service;
import com.marks.framework.dao.MapTagMapper;
import com.marks.framework.entity.MapTag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created 16/9/28 下午5:59
*
* @memo
*/
@Service
public class TagMapService {
@Autowired
private MapTagMapper mapTagMapper;
@Cacheable("testCache")
public List selectAll() {
List list = mapTagMapper.selectAll();
return list;
}
@CacheEvict("testCache")
public int insertTag() {
MapTag tag = new MapTag();
tag.setName("test1");
return mapTagMapper.insertSelective(tag);
}
}
controller
package com.marks.framework.controller;
import com.github.pagehelper.PageInfo;
import com.marks.framework.service.TagMapService;
import com.marks.framework.service.TestTagService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* Created 16/9/28 下午6:02
*
* @memo
*/
@Controller
public class TestApi {
Logger logger = Logger.getLogger(TestApi.class);
@Autowired
private TagMapService tagMapService;
@Autowired
private TestTagService testTagService;
@ResponseBody
@RequestMapping("/test1")
public List showTest() {
long start = System.currentTimeMillis();
List list = tagMapService.selectAll();
logger.error("所用的时间为:"+(System.currentTimeMillis()-start));
return list;
}
@ResponseBody
@RequestMapping("/test2")
public PageInfo showTest2() {
return testTagService.selectPageInfo(1,10);
}
@ResponseBody
@RequestMapping("/test3")
public int showTest3() {
logger.error("执行了一个插入数据的操作");
return tagMapService.insertTag();
}
}
结果为:
[ERROR] 2016-09-29 10:31:27 TestApi@(TestApi.java:35):所用的时间为:235
[ERROR] 2016-09-29 10:31:39 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:31:46 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:31:56 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:31:59 TestApi@(TestApi.java:49):执行了一个插入数据的操作
[ERROR] 2016-09-29 10:32:05 TestApi@(TestApi.java:35):所用的时间为:82
[ERROR] 2016-09-29 10:32:12 TestApi@(TestApi.java:35):所用的时间为:1
[ERROR] 2016-09-29 10:32:22 TestApi@(TestApi.java:35):所用的时间为:0
[ERROR] 2016-09-29 10:32:34 TestApi@(TestApi.java:35):所用的时间为:0
2.测试分页
1.service
package com.marks.framework.service;
import com.github.pagehelper.PageInfo;
import com.marks.framework.entity.MapTag;
/**
* Created 16/9/28 下午6:11
*
* @memo
*/
public interface TestTagService extends IService<MapTag> {
PageInfo selectPageInfo(int page, int limit);
}
package com.marks.framework.service.imp;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.marks.framework.entity.MapTag;
import com.marks.framework.service.TestTagService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created 16/9/28 下午6:13
*
* @memo
*/
@Service
public class TestTagServiceImp extends BaseService<MapTag> implements TestTagService{
@Override
public PageInfo selectPageInfo(int page, int limit) {
PageHelper.startPage(page,limit);
List list = mapper.selectAll();
return new PageInfo(list);
}
}
IService
package com.marks.framework.service;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 通用接口
*/
@Service
public interface IService<T> {
T selectByKey(Object key);
int save(T entity);
int delete(Object key);
int updateAll(T entity);
int updateNotNull(T entity);
List<T> selectByExample(Object example);
//TODO 其他...
}
baseService
package com.marks.framework.service.imp;
import com.marks.framework.service.IService;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
/**
* Created by liuzh on 2014/12/11.
*/
public abstract class BaseService<T> implements IService<T> {
@Autowired
protected Mapper<T> mapper;
public Mapper<T> getMapper() {
return mapper;
}
@Override
public T selectByKey(Object key) {
return mapper.selectByPrimaryKey(key);
}
public int save(T entity) {
return mapper.insert(entity);
}
public int delete(Object key) {
return mapper.deleteByPrimaryKey(key);
}
public int updateAll(T entity) {
return mapper.updateByPrimaryKey(entity);
}
public int updateNotNull(T entity) {
return mapper.updateByPrimaryKeySelective(entity);
}
public List<T> selectByExample(Object example) {
return mapper.selectByExample(example);
}
//TODO 其他...
}
controller 之前的代码贴过 就不贴了 看之前的
结果:
{
"pageNum": 1,
"pageSize": 10,
"size": 10,
"orderBy": null,
"startRow": 1,
"endRow": 10,
"total": 2859,
"pages": 286,
"list": [
{
"id": 143,
"name": "宁河分线1#",
"longitude": "120.195322",
"latitude": "30.355647",
"city": null,
"state": "1",
"img": "0",
"memo": "",
"address": null,
"isMove": 0,
"createTime": 1463381982000
},
{
"id": 144,
"name": "田安一站",
"longitude": "120.195378",
"latitude": "30.35531",
"city": null,
"state": "1",
"img": "1",
"memo": "田园河畔居4幢地下室",
"address": null,
"isMove": 0,
"createTime": 1463382127000
},
{
"id": 145,
"name": "宁河站",
"longitude": "120.194731",
"latitude": "30.355662",
"city": null,
"state": "1",
"img": "0",
"memo": "半山路新时代幼儿园旁(宁河弄附近)",
"address": null,
"isMove": 0,
"createTime": 1463382727000
},
{
"id": 147,
"name": "园野站",
"longitude": "120.194533",
"latitude": "30.355455",
"city": null,
"state": "1",
"img": "0",
"memo": "半山路公交终点站旁(公共自行车停放点旁/路口垃圾箱后面)",
"address": null,
"isMove": 0,
"createTime": 1463383631000
},
{
"id": 148,
"name": "田畔站",
"longitude": "120.195005",
"latitude": "30.355204",
"city": null,
"state": "1",
"img": "0",
"memo": "半山公交总站东南角房子内 拱墅半山供电营业厅旁)",
"address": null,
"isMove": 0,
"createTime": 1463383743000
},
{
"id": 149,
"name": "田安二站",
"longitude": "120.195472",
"latitude": "30.354803",
"city": null,
"state": "1",
"img": "0",
"memo": "田园河畔居7-8幢之间",
"address": null,
"isMove": 0,
"createTime": 1463383872000
},
{
"id": 150,
"name": "玻宿二站",
"longitude": "120.195388",
"latitude": "30.356453",
"city": null,
"state": "1",
"img": "0",
"memo": "半山宁河弄1幢旁",
"address": null,
"isMove": 0,
"createTime": 1463384069000
},
{
"id": 151,
"name": "明园一、二站",
"longitude": "120.193717",
"latitude": "30.356389",
"city": null,
"state": "1",
"img": "0",
"memo": "明园路小区旁",
"address": null,
"isMove": 0,
"createTime": 1463384177000
},
{
"id": 152,
"name": "山安站",
"longitude": "120.192122",
"latitude": "30.354577",
"city": null,
"state": "1",
"img": "0",
"memo": "半山路87号城北大厦南面半山家苑6幢3号",
"address": null,
"isMove": 0,
"createTime": 1463384379000
},
{
"id": 153,
"name": "钢宿站",
"longitude": "120.191182",
"latitude": "30.355051",
"city": null,
"state": "1",
"img": "0",
"memo": "半山路行钢南苑16幢东面的公共厕所后面",
"address": null,
"isMove": 0,
"createTime": 1463384489000
}
],
"firstPage": 1,
"prePage": 0,
"nextPage": 2,
"lastPage": 8,
"isFirstPage": true,
"isLastPage": false,
"hasPreviousPage": false,
"hasNextPage": true,
"navigatePages": 8,
"navigatepageNums": [
1,
2,
3,
4,
5,
6,
7,
8
]
}
具体的参数请参考 https://github.com/pagehelper/Mybatis-PageHelper
3.测试shiro
package com.marks.framework.security;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;
/**
*
*配置文件的组件bean
*
*
**/
@Component(value = "securityRealm")
public class SecurityRealm extends AuthorizingRealm {
Logger logger = Logger.getLogger(SecurityRealm.class);
/**
* 权限检查
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
String username = String.valueOf(principals.getPrimaryPrincipal());
logger.error("doGetAuthorizationInfo==" + username);
authorizationInfo.addRole("admin");
authorizationInfo.addStringPermission("user:create");
authorizationInfo.addStringPermission("add");
return authorizationInfo;
}
/**
* 登录验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = String.valueOf(token.getPrincipal());
String password = new String((char[]) token.getCredentials());
logger.error("doGetAuthenticationInfo:" + "username=" + username + " password:" + password);
if (!username.equals("admin") && !password.equals("123456")) {
throw new AuthenticationException("用户名或密码错误.");
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName());
return authenticationInfo;
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>我是登录的界面</title>
</head>
<body>
<span>请先登录</span>
<form action="/rest/user/login" method="post">
<input type="text" name="username" required/>
<input type="password" name="password" required/>
<input type="submit" value="on click"/>
</form>
</body>
</html>
main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<title>I am main</title>
</head>
<body>
<span>欢迎来到首页,<shiro:principal/></span>
<table>
<tr><td><shiro:authenticated>用户已经登录显示此内容</shiro:authenticated></td></tr>
<tr><td><shiro:hasRole name="manager">manager角色登录显示此内容</shiro:hasRole></td></tr>
<tr><td><shiro:hasRole name="admin">admin角色登录显示此内容</shiro:hasRole></td></tr>
<tr><td><shiro:hasRole name="normal">normal角色登录显示此内容</shiro:hasRole></td></tr>
<tr><td><shiro:hasAnyRoles name="manager,admin">**manager or admin 角色用户登录显示此内容**</shiro:hasAnyRoles></td></tr>
<tr><td> <shiro:principal/>-显示当前登录用户名</td></tr>
<tr> <td><shiro:hasPermission name="add">add权限用户显示此内容</shiro:hasPermission></td></tr>
<tr><td><shiro:hasPermission name="user:query">query权限用户显示此内容<shiro:principal/></shiro:hasPermission></td></tr>
<tr><td> <shiro:hasPermission name="user:create">user:create权限用户显示此内容<shiro:principal/></shiro:hasPermission></td></tr>
<tr><td><shiro:lacksPermission name="user:del"> 不具有user:del权限的用户显示此内容 </shiro:lacksPermission></td></tr>
</table>
</body>
</html>
测试:
图1.
图2
图3
图4
总结:
在整合的时候有些地方只是考虑到简单的整合,所以要运用到正真开发的项目还需要自己按照需求进行修改。