本文章牵涉到的技术点比较多:spring Data JPA、Redis、Spring MVC,Spirng Cache,所以在看这篇文章的时候,需要对以上这些技术点有一定的了解或者也可以先看看这篇文章,针对文章中实际的技术点在进一步了解(注意,您需要自己下载Redis Server到您的本地,所以确保您本地的Redis可用,这里还使用了MySQL数据库,当然你也可以内存数据库进行测试)。这篇文章会提供对应的Eclipse代码示例,具体大体的分如下几个步骤:
(1)新建Java Maven Project;
(2)在pom.xml中添加相应的依赖包;
(3)编写Spring Boot启动类;
(4)配置application.properties;
(5)编写RedisCacheConfig配置类;
(6)编写DemoInfo测试实体类;
(7)编写DemoInfoRepository持久化类;
(8)编写DemoInfoService类;
(9)编写DemoInfoController类;
(10)测试代码是否正常运行了
(11)自定义缓存key;
(1)新建Java Maven Project;
这个步骤就不细说,新建一个spring-boot-redis Java maven project;
(2)在pom.xml中添加相应的依赖包;
在Maven中添加相应的依赖包,主要有:spring boot 父节点依赖;spring boot web支持;缓存服务spring-context-support;添加redis支持;JPA操作数据库;mysql 数据库驱动,具体pom.xml文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kfit</groupId> <artifactId>spring-boot-redis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-redis</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 配置JDK编译版本. --> <java.version>1.8</java.version> </properties> <!-- spring boot 父节点依赖, 引入这个之后相关的引入就不需要添加version配置, spring boot会自动选择最合适的版本进行添加。 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!-- spring boot web支持:mvc,aop... --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 包含支持UI模版(Velocity,FreeMarker,JasperReports), 邮件服务, 脚本服务(JRuby), 缓存Cache(EHCache), 任务计划Scheduling(uartz)。 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- 添加redis支持--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <!-- JPA操作数据库. --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- mysql 数据库驱动. --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 单元测试. --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
上面是完整的pom.xml文件,每个里面都进行了简单的注释。
(3)编写Spring Boot启动类(com.kfit.App);
package com.kfit; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Spring Boot启动类; * * @author Angel(QQ:*********) * @version v.0.1 */ @SpringBootApplication public class App { /** * -javaagent:.\lib\springloaded-1.2.4.RELEASE.jar -noverify * @param args */ public static void main(String[] args) { SpringApplication.run(App.class, args); } }
(4)配置application.properties;
这里主要是配置两个资源,第一就是数据库基本信息;第二就是redis配置;第三就是JPA的配置;
Src/main/resouces/application.properties: ######################################################## ###datasource 配置MySQL数据源; ######################################################## spring.datasource.url = jdbc:mysql://localhost:3306/test spring.datasource.username = root spring.datasource.password = root spring.datasource.driverClassName = com.mysql.jdbc.Driver spring.datasource.max-active=20 spring.datasource.max-idle=8 spring.datasource.min-idle=8 spring.datasource.initial-size=10 ######################################################## ###REDIS (RedisProperties) redis基本配置; ######################################################## # database name spring.redis.database=0 # server host1 spring.redis.host=127.0.0.1 # server password #spring.redis.password= #connection port spring.redis.port=6379 # pool settings ... spring.redis.pool.max-idle=8 spring.redis.pool.min-idle=0 spring.redis.pool.max-active=8 spring.redis.pool.max-wait=-1 # name of Redis server #spring.redis.sentinel.master= # comma-separated list of host:port pairs #spring.redis.sentinel.nodes= ######################################################## ### Java Persistence Api 自动进行建表 ######################################################## # Specify the DBMS spring.jpa.database = MYSQL # Show or not log for each sql query spring.jpa.show-sql = true # hibernate ddl auto (create, create-drop, update) spring.jpa.hibernate.ddl-auto = update # Naming strategy spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy # stripped before adding them to the entity manager) spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
(5)编写RedisCacheConfig配置类;
缓存主要有几个要实现的类:其一就是CacheManager缓存管理器;其二就是具体操作实现类;其三就是CacheManager工厂类(这个可以使用配置文件配置的进行注入,也可以通过编码的方式进行实现);其四就是缓存key生产策略(当然Spring自带生成策略,但是在Redis客户端进行查看的话是系列化的key,对于我们肉眼来说就是感觉是乱码了,这里我们先使用自带的缓存策略)。
com.kfit.config/RedisCacheConfig: package com.kfit.config; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; /** * redis 缓存配置; * * 注意:RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了; * * 这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。 * * 普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。 * * @author Angel(QQ:412887952) * @version v.0.1 */ @Configuration @EnableCaching//启用缓存,这个注解很重要; publicclass RedisCacheConfig extends CachingConfigurerSupport { /** * 缓存管理器. * @param redisTemplate * @return */ @Bean public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) { CacheManager cacheManager = new RedisCacheManager(redisTemplate); returncacheManager; } /** * redis模板操作类,类似于jdbcTemplate的一个类; * * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活; * * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们 * * 自己的缓存类,比如:RedisStorage类; * * @param factory : 通过Spring进行注入,参数在application.properties进行配置; * @return */ @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>(); redisTemplate.setConnectionFactory(factory); //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误; //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer //或者JdkSerializationRedisSerializer序列化方式; // RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息; // redisTemplate.setKeySerializer(redisSerializer); // redisTemplate.setHashKeySerializer(redisSerializer); returnredisTemplate; } }
在以上代码有很详细的注释,在这里还是在简单的提下:
RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了;这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。
(6)编写DemoInfo测试实体类;
编写一个测试实体类:com.kfit.bean.DemoInfo:
package com.kfit.bean; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; /** * 测试实体类,这个随便; * @author Angel(QQ:412887952) * @version v.0.1 */ @Entity publicclass DemoInfo implements Serializable{ privatestaticfinallongserialVersionUID = 1L; @Id@GeneratedValue privatelongid; private String name; private String pwd; publiclong getId() { returnid; } publicvoid setId(longid) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public String getPwd() { returnpwd; } publicvoid setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return"DemoInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + "]"; } }
(7)编写DemoInfoRepository持久化类;
DemoInfoRepository使用Spirng Data JPA实现:
com.kfit.repository.DemoInfoRepository: package com.kfit.repository; import org.springframework.data.repository.CrudRepository; import com.kfit.bean.DemoInfo; /** * DemoInfo持久化类 * @author Angel(QQ:412887952) * @version v.0.1 */ publicinterface DemoInfoRepository extends CrudRepository<DemoInfo,Long> { }
(8)编写DemoInfoService类;
编写DemoInfoService,这里有两个技术方面,第一就是使用Spring @Cacheable注解方式和RedisTemplate对象进行操作,具体代码如下:
com.kfit.service.DemoInfoService:
package com.kfit.service; import com.kfit.bean.DemoInfo; /** * demoInfo 服务接口 * @author Angel(QQ:412887952) * @version v.0.1 */ publicinterface DemoInfoService { public DemoInfo findById(longid); publicvoid deleteFromCache(longid); void test(); } com.kfit.service.impl.DemoInfoServiceImpl: package com.kfit.service.impl; import javax.annotation.Resource; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import com.kfit.bean.DemoInfo; import com.kfit.repository.DemoInfoRepository; import com.kfit.service.DemoInfoService; /** * *DemoInfo数据处理类 * * @author Angel(QQ:412887952) * @version v.0.1 */ @Service publicclass DemoInfoServiceImpl implements DemoInfoService { @Resource private DemoInfoRepository demoInfoRepository; @Resource private RedisTemplate<String,String> redisTemplate; @Override publicvoid test(){ ValueOperations<String,String> valueOperations = redisTemplate.opsForValue(); valueOperations.set("mykey4", "random1="+Math.random()); System.out.println(valueOperations.get("mykey4")); } //keyGenerator="myKeyGenerator" @Cacheable(value="demoInfo") //缓存,这里没有指定key. @Override public DemoInfo findById(longid) { System.err.println("DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id="+id); returndemoInfoRepository.findOne(id); } @CacheEvict(value="demoInfo") @Override publicvoid deleteFromCache(longid) { System.out.println("DemoInfoServiceImpl.delete().从缓存中删除."); } }
(9)编写DemoInfoController类;
package com.kfit.controller; 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 com.kfit.bean.DemoInfo; import com.kfit.service.DemoInfoService; /** * 测试类. * @author Angel(QQ:412887952) * @version v.0.1 */ @Controller publicclass DemoInfoController { @Autowired DemoInfoService demoInfoService; @RequestMapping("/test") public@ResponseBody String test(){ DemoInfo loaded = demoInfoService.findById(1); System.out.println("loaded="+loaded); DemoInfo cached = demoInfoService.findById(1); System.out.println("cached="+cached); loaded = demoInfoService.findById(2); System.out.println("loaded2="+loaded); return"ok"; } @RequestMapping("/delete") public@ResponseBody String delete(longid){ demoInfoService.deleteFromCache(id); return"ok"; } @RequestMapping("/test1") public@ResponseBody String test1(){ demoInfoService.test(); System.out.println("DemoInfoController.test1()"); return"ok"; } }
(10)测试代码是否正常运行了
启动应用程序,访问地址:127.0.0.1:8080/test
查看控制台可以查看:
DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1
loaded=DemoInfo [id=1, name=张三, pwd=123456]
cached=DemoInfo [id=1, name=张三, pwd=123456]
DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=2
loaded2=DemoInfo [id=2, name=张三, pwd=123456]
如果你看到以上的打印信息的话,那么说明缓存成功了。
访问地址:127.0.0.1:8080/test1
random1=0.9985031320746356
DemoInfoController.test1()
二次访问:http://127.0.0.1:8080/test
loaded=DemoInfo [id=1, name=张三, pwd=123456]
cached=DemoInfo [id=1, name=张三, pwd=123456]
loaded2=DemoInfo [id=2, name=张三, pwd=123456]
这时候所有的数据都是执行缓存的。
这时候执行删除动作:127.0.0.1:8080/delete?id=1
然后在访问:127.0.0.1:8080/test
DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1
loaded=DemoInfo [id=1, name=张三, pwd=123456]
cached=DemoInfo [id=1, name=张三, pwd=123456]
loaded2=DemoInfo [id=2, name=张三, pwd=123456]
(11)自定义缓存key;
在com.kfit.config.RedisCacheConfig类中重写CachingConfigurerSupport中的keyGenerator ,具体实现代码如下:
/** * 自定义key. * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 */ @Override public KeyGenerator keyGenerator() { System.out.println("RedisCacheConfig.keyGenerator()"); returnnew KeyGenerator() { @Override public Object generate(Object o, Method method, Object... objects) { // This will generate a unique key of the class name, the method name //and all method parameters appended. StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()); sb.append(method.getName()); for (Object obj : objects) { sb.append(obj.toString()); } System.out.println("keyGenerator=" + sb.toString()); returnsb.toString(); } }; }
这时候在redis的客户端查看key的话还是序列化的肉眼看到就是乱码了,那么我改变key的序列方式,这个很简单,redis底层已经有具体的实现类了,我们只需要配置下:
//key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误; //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer //或者JdkSerializationRedisSerializer序列化方式; RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息; redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer);
综上以上分析:RedisCacheConfig类的方法调整为:
package com.kfit.config; import java.lang.reflect.Method; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * redis 缓存配置; * * 注意:RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了; * * 这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。 * * 普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。 * * @author Angel(QQ:412887952) * @version v.0.1 */ @Configuration @EnableCaching//启用缓存,这个注解很重要; publicclass RedisCacheConfig extends CachingConfigurerSupport { /** * 缓存管理器. * @param redisTemplate * @return */ @Bean public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) { CacheManager cacheManager = new RedisCacheManager(redisTemplate); returncacheManager; } /** * RedisTemplate缓存操作类,类似于jdbcTemplate的一个类; * * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活; * * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们 * * 自己的缓存类,比如:RedisStorage类; * * @param factory : 通过Spring进行注入,参数在application.properties进行配置; * @return */ @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>(); redisTemplate.setConnectionFactory(factory); //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误; //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer //或者JdkSerializationRedisSerializer序列化方式; RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息; redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); returnredisTemplate; } /** * 自定义key. * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 */ @Override public KeyGenerator keyGenerator() { System.out.println("RedisCacheConfig.keyGenerator()"); returnnew KeyGenerator() { @Override public Object generate(Object o, Method method, Object... objects) { // This will generate a unique key of the class name, the method name //and all method parameters appended. StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()); sb.append(method.getName()); for (Object obj : objects) { sb.append(obj.toString()); } System.out.println("keyGenerator=" + sb.toString()); returnsb.toString(); } }; } }
这时候在访问地址:127.0.0.1:8080/test
这时候看到的Key就是:com.kfit.service.impl.DemoInfoServiceImplfindById1
在控制台打印信息是:
(1)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1
(2)DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1
(3)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1
(4)loaded=DemoInfo [id=1, name=张三, pwd=123456]
(5)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1
(6)cached=DemoInfo [id=1, name=张三, pwd=123456]
(7)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById2
(8)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById2
(10)DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=2
(11)loaded2=DemoInfo [id=2, name=张三, pwd=123456]
其中@Cacheable,@CacheEvict下节进行简单的介绍,这节的东西实在是太多了,到这里就打住吧,剩下的就需要靠你们自己进行扩展了。
Atas ialah kandungan terperinci 缓存机制中Spring Boot集成Redis的方法介绍. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Artikel ini membincangkan menggunakan Maven dan Gradle untuk Pengurusan Projek Java, membina automasi, dan resolusi pergantungan, membandingkan pendekatan dan strategi pengoptimuman mereka.

Artikel ini membincangkan membuat dan menggunakan perpustakaan Java tersuai (fail balang) dengan pengurusan versi dan pergantungan yang betul, menggunakan alat seperti Maven dan Gradle.

Artikel ini membincangkan pelaksanaan caching pelbagai peringkat di Java menggunakan kafein dan cache jambu untuk meningkatkan prestasi aplikasi. Ia meliputi persediaan, integrasi, dan faedah prestasi, bersama -sama dengan Pengurusan Dasar Konfigurasi dan Pengusiran PRA Terbaik

Artikel ini membincangkan menggunakan JPA untuk pemetaan objek-relasi dengan ciri-ciri canggih seperti caching dan pemuatan malas. Ia meliputi persediaan, pemetaan entiti, dan amalan terbaik untuk mengoptimumkan prestasi sambil menonjolkan potensi perangkap. [159 aksara]

Kelas kelas Java melibatkan pemuatan, menghubungkan, dan memulakan kelas menggunakan sistem hierarki dengan bootstrap, lanjutan, dan pemuat kelas aplikasi. Model delegasi induk memastikan kelas teras dimuatkan dahulu, yang mempengaruhi LOA kelas tersuai

Artikel ini menerangkan Java's Remote Method Invocation (RMI) untuk membina aplikasi yang diedarkan. IT memperincikan definisi antara muka, pelaksanaan, persediaan pendaftaran, dan penyerahan klien, menangani cabaran seperti isu rangkaian dan keselamatan.

Artikel ini memperincikan API soket Java untuk komunikasi rangkaian, yang meliputi persediaan pelanggan-pelayan, pengendalian data, dan pertimbangan penting seperti pengurusan sumber, pengendalian ralat, dan keselamatan. Ia juga meneroka teknik pengoptimuman prestasi, i

Butiran artikel ini mewujudkan protokol rangkaian Java tersuai. Ia meliputi definisi protokol (struktur data, pembingkaian, pengendalian ralat, versi), pelaksanaan (menggunakan soket), serialisasi data, dan amalan terbaik (kecekapan, keselamatan, mainta


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

mPDF
mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),

SublimeText3 Linux versi baharu
SublimeText3 Linux versi terkini

Dreamweaver Mac版
Alat pembangunan web visual

SublimeText3 versi Inggeris
Disyorkan: Versi Win, menyokong gesaan kod!

DVWA
Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini