1. Spring-data-redis Introduction
Encapsulates the Redis client, making it easier to use.
The advantage is that the client connection is placed in a connection pool to improve performance. There is also the ability to switch between different clients without changing one line of code (a technique that spring is accustomed to).
The latest version of this writing is 1.3,
Currently supports the following 4 types of Java clients, which are free to switch without changing the code.
2. Twitter Introduction
Twitter, if not used, can be understood to be similar to the domestic Sina Weibo. Because of the huge number of visits and users of Weibo, the traditional relational database is not supported, so a non-relational database architecture with Redis is designed.
In this article we will use Spring-data-redis to implement a Twitter-like website.
3. Environment
I am a pro-test through the environment
JDK 1.6.0_45 64bit
Gradle 1.7
Tomcat 7.0.35
Redis 2.8.11 Win64
Jedis 2.5.1
Spring 3.2.9
Spring-data-redis 1.3.0
4. First hands-on operation
4.1 First git clone the following items
Https://github.com/spring-projects/spring-data-keyvalue-examples/tree/master/retwisj
4.2 I made some changes, some 3pp change the cost of writing the latest version of the text
Build.gradle
Java code
- Compile "redis.clients:jedis:2.5.1"
Gradle.properties
Java code
- Springversion = 3.2. 9.RELEASE
- Springredisversion = 1.3. 0.RELEASE
4.3 compiling
Java code
- Gradle Build
4.4 Put Retwisj.war into Tomcat's WebApp directory and start Tomcat
4.5 Visit HTTP://LOCALHOST:8080/RETWISJ
Take a few minutes to play and get familiar with the features.
Well, we've done a microblogging site. All right, let's have a brief analysis of the code implementation.
5. Implementation analysis
5.1 Table Structure Design
5.1.1 Users (user)
Using the previous relational database design is like this
Key |
Username |
Password |
1 |
Springrod |
Interface21 |
2 |
Costinl |
This was fun |
And with Redis, it turns out that
Key |
Type |
Value |
Uid:1 |
Hash |
{Name:springrod, PASS:INTERFACE21} |
Uid:2 |
Hash |
{name:costinl, Pass:secret} |
Deposit the user's name and password as a hash
The corresponding Redis native command is
Java code
- Hmset User:1 name Springrod pass INTERFACE21
The UID is self-growing and can be implemented using Redis's incr, which is an atomic operation
Java code
- INCR Global:uid
Key |
Type |
Value |
Global:uid |
String |
2 |
We want to preserve the correspondence between the username and the UID, such as when a user logs in, we need to get his UID. You can create an inverted key to implement this function. User:[name]:uid
A list that users use to hold all the UID is also created.
Key |
Type |
Value |
User:springrod:uid |
String |
1 |
User:costinl:uid |
String |
2 |
Users |
List |
{1, 2} |
5.1.2 Weibo (Post)
Similarly, use Global:pid to record self-growing post IDs
Key |
Type |
Value |
Global:pid |
String |
2 |
Deposit the content, time, and author of the Weibo as a hash
Key |
Type |
Value |
Pid:1 |
Hash |
{Content:hello World, time:1301931414757, uid:1} |
Pid:2 |
Hash |
{content:working on some cool stuff, time:1301931414897, uid:1} |
Pid:3 |
Hash |
{content:checking out retwisj, time:1301931454897, uid:2} |
All of a user's Weibo
Key |
Type |
Value |
Uid:1:posts |
List |
{1, 2} |
Uid:2:posts |
List |
{3} |
All Micro-Blog listings (Timeline)
Key |
Type |
Value |
Timeline |
List |
{1, 2, 3} |
5.1.3 Relationship (Fan (Follower), concern (following))
For example, user2 concerned about User1, then User2 is a fan of User1,
User3 also focused on the User1,
Then User1 was user2,user3 by the attention
Key |
Type |
Value |
Uid:1:followers |
Set |
{2,3} |
Uid:2:following |
Set |
{1} |
Uid:3:following |
Set |
{1} |
Sina Weibo on the Chen Yao fans have 70 million, the light record her a person's fans will be 70 million records.
If implemented with a traditional relational database, the pressure is high.
5.2 Security Verification
We do not use the session to track the user, but with cookies.
Each time a user logs in, generates a random number (token) for him, sends it to the user, and lets him save as a cookie, which is used to authenticate the user.
The same storage of an inverted key, can be based on the cookie to obtain the UID
Key |
Type |
Value |
Uid:2:auth |
String |
{FEA5E81AC8CA77622BED1C2132A021F9} |
Auth:fea5e81ac8ca77622bed1c2132a021f9 |
String |
{2} |
5.3 Structure of the package
Org.springframework.data.redis.sample.retwisj.web |
Web tier |
Org.springframework.data.redis.sample.retwisj.redis |
Persistence layer |
Org.springframework.data.redis.sample.retwisj |
Domain Layer |
5.4 Using Redistemplate
Applicationcontext-redis.xml
XML code
- <beans>
- <context:property-placeholder location="classpath:redis.properties"/>
- <!--Redis Client This is where the code is not changed to achieve different client switching, we use jedis-->
- <Bean id= "connectionfactory" class=" Org.springframework.data.redis.connection.jedis.JedisConnectionFactory "
- p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"/ >
- <Bean id= "redistemplate" class=" Org.springframework.data.redis.core.StringRedisTemplate "
- p:connection-factory-ref="connectionfactory"/>
- <context:annotation-config />
- <context:component-scan base-package="org.springframework.data.redis.samples"/>
- </Beans>
5.5 Web Layer
Using spring MVC and JSP
5.5.1 Controller Layer
Retwiscontroller
5.5.2 Cookieinterceptor
For user authentication, a spring MVC interceptor was written in a cookie-based way
Java code
- Public class Cookieinterceptor extends Handlerinterceptoradapter
and configure it in the Retwisj-servlet.xml.
XML code
- <mvc:interceptors>
- <Bean class="Org.springframework.data.redis.samples.retwisj.web.CookieInterceptor" / >
- </mvc:interceptors>
The effect is to save the user's token by saving a cookie called "Retwisauth" on the client.
5.5.3 I18
Cookielocaleresolver the presence of language as a cookie client
XML code
- <Bean id= "localeresolver" class=" Org.springframework.web.servlet.i18n.CookieLocaleResolver "/>
The effect is to save the language by saving a cookie called "Org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE" on the client.
Localechangeinterceptor can be used to change language
XML code
- <mvc:interceptors>
- <Bean class="Org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramname= "lang"/>
- </mvc:interceptors>
This way, you can change the language by HTTP://LOCALHOST:8080/RETWISJ/?LANG=CN.
5.6 Persistence Layer
Retwisrepository
The following code example demonstrates how to use Intersect to find the same fan for 2 users
Java code
- Private redisset<string> following (String uid) {
- return New defaultredisset<string> (keyutils.following (UID), template);
- }
- Public list<string> commonfollowers (string uid, string targetuid) {
- Redisset<string> Tempset = following (UID). Intersectandstore (Following (Targetuid),
- Keyutils.commonfollowers (UID, targetuid));
- Tempset.expire (5, timeunit.seconds);
- return Covertuidstonames (Tempset.getkey ());
- }
The following code example uses Redisatomiclong to implement self-growing id,boundhashoperations to store the user's user name and password
Java code
- public string AddUser (string name, string password) {
- String uid = string.valueof (Useridcounter.incrementandget ());
- //Save user as hash
- //UID-user
- Boundhashoperations<string, String, string> userops = Template.boundhashops (Keyutils.uid (UID));
- Userops.put ("name", name);
- Userops.put ("pass", password);
- Valueops.set (Keyutils.user (name), UID);
- Users.addfirst (name);
- return Addauth (name);
- }
http://xpenxpen.iteye.com/blog/2082966
Use Spring-data-redis to implement Twitter-like websites (go)