Skip to content

Commit e1d9cdd

Browse files
committed
implemented visitors counting and likes/dislikes
1 parent ffd1c74 commit e1d9cdd

55 files changed

Lines changed: 620 additions & 140 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ SpringBlog is powered by many powerful frameworks and third-party projects:
2222

2323
## Changelog
2424

25+
#### 2017-11-15
26+
27+
* Implemented visitors counting (depends on X-Real-IP header)
28+
* Implemented likes/dislikes (depends on X-Real-IP header)
29+
2530
#### 2017-11-14
2631

2732
* Added RememberMe checkbox into login form, increased RememberMe cookie timeout upto 7 days

build.gradle

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ apply plugin: 'spring-boot'
77
sourceCompatibility = 1.8
88
targetCompatibility = 1.8
99

10-
version = '2.6.2'
10+
version = '2.7.0'
1111

1212
repositories {
1313
mavenLocal()
@@ -59,10 +59,6 @@ dependencies {
5959
compile 'de.neuland-bfi:spring-jade4j:1.2.7'
6060
compile 'org.pegdown:pegdown:1.6.0'
6161

62-
// python
63-
//compile 'org.python:jython-standalone:2.7.1'
64-
//compile 'org.pygments:pygments:2.2.0'
65-
6662
//markdown processor
6763
compile 'com.vladsch.flexmark:flexmark-all:0.27.0'
6864

@@ -100,6 +96,9 @@ dependencies {
10096
compile 'org.projectlombok:lombok:1.16.16'
10197
//compile 'com.qiniu:qiniu-java-sdk:7.0.+'
10298

99+
// JSON support
100+
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.2'
101+
103102
// static resources, ref. http://www.webjars.org/
104103
compile 'org.webjars:jquery:3.2.1'
105104
compile 'org.webjars:bootstrap:3.3.7-1'

src/main/java/com/raysmond/blog/controllers/PostController.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
import com.raysmond.blog.Constants;
44
import com.raysmond.blog.error.NotFoundException;
55
import com.raysmond.blog.models.Post;
6-
import com.raysmond.blog.services.PostService;
7-
import com.raysmond.blog.services.TagService;
8-
import com.raysmond.blog.services.UserService;
6+
import com.raysmond.blog.services.*;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
99
import org.springframework.beans.factory.annotation.Autowired;
1010
import org.springframework.stereotype.Controller;
1111
import org.springframework.ui.Model;
1212
import org.springframework.web.bind.annotation.PathVariable;
1313
import org.springframework.web.bind.annotation.RequestMapping;
1414

15+
import javax.servlet.http.HttpServletRequest;
1516
import java.util.List;
1617
import java.util.Set;
1718

@@ -25,12 +26,24 @@
2526
@RequestMapping("posts")
2627
public class PostController {
2728

29+
Logger logger = LoggerFactory.getLogger(PostController.class);
30+
2831
@Autowired
2932
private PostService postService;
3033

3134
@Autowired
3235
private UserService userService;
3336

37+
@Autowired
38+
private VisitService visitService;
39+
40+
@Autowired
41+
private LikeService likeService;
42+
43+
@Autowired
44+
private RequestProcessorService requestProcessorService;
45+
46+
3447
@RequestMapping(value = "archive", method = GET)
3548
public String archive(Model model){
3649
model.addAttribute("posts", postService.getArchivePosts());
@@ -39,26 +52,14 @@ public String archive(Model model){
3952
}
4053

4154
@RequestMapping(value = "{permalink}", method = GET)
42-
public String show(@PathVariable String permalink, Model model){
43-
Post post = null;
44-
45-
try{
46-
post = this.postService.getPublishedPostByPermalink(permalink);
47-
} catch (NotFoundException ex){
48-
if (permalink.matches("\\d+")) {
49-
if (this.userService.currentUser().isAdmin()) {
50-
post = this.postService.getPost(Long.valueOf(permalink));
51-
} else {
52-
post = this.postService.getPublishedPost(Long.valueOf(permalink));
53-
}
54-
} else if (permalink.toLowerCase().trim().equals(Constants.PROJECTS_PAGE_PERMALINK)) {
55-
post = this.postService.createProjectsPage();
56-
}
57-
}
58-
59-
if (post == null) {
60-
throw new NotFoundException("Post with permalink " + permalink + " is not found");
61-
}
55+
public String show(@PathVariable String permalink, Model model, HttpServletRequest request){
56+
Post post = this.postService.findPostByPermalink(permalink);
57+
58+
logger.debug(String.format("ACCESS %s from IP: %s", permalink, this.requestProcessorService.getRealIp(request)));
59+
60+
this.visitService.saveVisit(this.requestProcessorService.getRealIp(request), post);
61+
post.setVisitsCount(this.visitService.getUniqueVisitsCount(post));
62+
post.setSympathyCount(this.likeService.getTotalLikesByPost(post));
6263

6364
model.addAttribute("post", post);
6465
model.addAttribute("tags", this.postService.getPostTags(post));
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.raysmond.blog.controllers;
2+
3+
import com.raysmond.blog.forms.LikeForm;
4+
import com.raysmond.blog.models.Post;
5+
import com.raysmond.blog.services.*;
6+
import com.raysmond.blog.support.web.ViewHelper;
7+
import lombok.Data;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.stereotype.Controller;
10+
import org.springframework.web.bind.annotation.*;
11+
12+
import javax.servlet.http.HttpServletRequest;
13+
import javax.validation.constraints.NotNull;
14+
15+
@Controller
16+
@RequestMapping(value = "/sympathy")
17+
public class SympathyController {
18+
19+
@Autowired
20+
private AppSetting appSetting;
21+
22+
@Autowired
23+
private PostService postService;
24+
25+
@Autowired
26+
private LikeService likeService;
27+
28+
@Autowired
29+
private UserService userService;
30+
31+
@Autowired
32+
private RequestProcessorService requestProcessorService;
33+
34+
35+
@Data
36+
public static class SympathyRequestData {
37+
@NotNull
38+
private String postId;
39+
}
40+
41+
42+
@PostMapping(value = "/like")
43+
public @ResponseBody LikeForm likeIt(@RequestBody SympathyRequestData data, HttpServletRequest request) {
44+
Post post = this.postService.findPostByPermalink(data.getPostId());
45+
this.likeService.likePost(post, this.requestProcessorService.getRealIp(request));
46+
ViewHelper viewHelper = new ViewHelper(this.appSetting);
47+
LikeForm result = new LikeForm();
48+
result.setSympathy(viewHelper.formatNumberByThousands(this.likeService.getTotalLikesByPost(post)));
49+
return result;
50+
}
51+
52+
@PostMapping(value = "/dislike")
53+
public @ResponseBody LikeForm dislikeIt(@RequestBody SympathyRequestData data, HttpServletRequest request) {
54+
Post post = this.postService.findPostByPermalink(data.getPostId());
55+
this.likeService.dislikePost(post, this.requestProcessorService.getRealIp(request));
56+
ViewHelper viewHelper = new ViewHelper(this.appSetting);
57+
LikeForm result = new LikeForm();
58+
result.setSympathy(viewHelper.formatNumberByThousands(this.likeService.getTotalLikesByPost(post)));
59+
return result;
60+
}
61+
62+
63+
64+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.raysmond.blog.forms;
2+
3+
import lombok.Data;
4+
5+
import javax.validation.constraints.NotNull;
6+
7+
@Data
8+
public class LikeForm {
9+
10+
@NotNull
11+
private String sympathy = "0";
12+
13+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.raysmond.blog.models;
2+
3+
import lombok.Getter;
4+
import lombok.Setter;
5+
6+
import javax.persistence.Column;
7+
import javax.persistence.Entity;
8+
import javax.persistence.ManyToOne;
9+
import javax.persistence.Table;
10+
11+
@Entity
12+
@Table(name = "posts_likes")
13+
@Getter @Setter
14+
public class Like extends BaseModel {
15+
16+
@ManyToOne
17+
private User user;
18+
19+
@ManyToOne
20+
private Post post;
21+
22+
@Column(nullable = false)
23+
private Integer sympathy;
24+
25+
@Column(nullable = false)
26+
private String clientIp;
27+
28+
@Column(nullable = false, columnDefinition = "boolean default false")
29+
private Boolean isAdmin;
30+
31+
}

src/main/java/com/raysmond/blog/models/Post.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,15 @@ public void setPermalink(String permalink){
7575
this.permalink = StringUtils.arrayToDelimitedString(StringUtils.tokenizeToStringArray(token, " "), "-");
7676
}
7777

78+
private Long visitsCount = 0L;
79+
public Long getVisitsCount() {
80+
if (this.visitsCount == null) return 0L;
81+
else return this.visitsCount;
82+
}
83+
84+
private Integer sympathyCount = 0;
85+
public Integer getSympathyCount() {
86+
if (this.sympathyCount == null) return 0;
87+
else return this.sympathyCount;
88+
}
7889
}

src/main/java/com/raysmond/blog/models/StoredFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class StoredFile extends BaseModel {
2929
@Column(columnDefinition = "bigint default 0")
3030
private Long size;
3131

32-
public String getSizeForHuman() {
32+
public String getSizeFormatted() {
3333
double bytes = this.getSize();
3434
double kilobytes = (bytes / 1024);
3535
double megabytes = (kilobytes / 1024);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.raysmond.blog.models;
2+
3+
import lombok.Getter;
4+
import lombok.Setter;
5+
6+
import javax.persistence.Column;
7+
import javax.persistence.Entity;
8+
import javax.persistence.ManyToOne;
9+
import javax.persistence.Table;
10+
11+
@Entity
12+
@Table(name = "visits")
13+
@Getter @Setter
14+
public class Visit extends BaseModel {
15+
16+
@ManyToOne
17+
private User user;
18+
19+
@Column(nullable = false)
20+
private String clientIp;
21+
22+
@ManyToOne
23+
private Post post;
24+
25+
@Column(nullable = false, columnDefinition = "boolean default false")
26+
private Boolean isAdmin;
27+
28+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.raysmond.blog.repositories;
2+
3+
import com.raysmond.blog.models.Like;
4+
import com.raysmond.blog.models.Post;
5+
import com.raysmond.blog.models.User;
6+
import org.springframework.data.jpa.repository.JpaRepository;
7+
import org.springframework.data.jpa.repository.Query;
8+
import org.springframework.data.repository.query.Param;
9+
import org.springframework.stereotype.Repository;
10+
11+
@Repository
12+
public interface LikeRepository extends JpaRepository<Like, Long> {
13+
14+
@Query("SELECT SUM(l.sympathy) FROM Like AS l WHERE l.user = :user AND l.post = :post GROUP BY l.user, l.post")
15+
Integer getTotalLikesByUserAndPost(@Param("user") User user, @Param("post") Post post);
16+
17+
@Query("SELECT SUM(l.sympathy) FROM Like AS l WHERE l.post = :post GROUP BY l.post")
18+
Integer getTotalLikesByPost(@Param("post") Post post);
19+
20+
@Query("SELECT SUM(l.sympathy) FROM Like AS l WHERE l.clientIp = :clientIp AND l.post = :post GROUP BY l.clientIp, l.post")
21+
Integer getTotalLikesByClientIpAndPost(@Param("clientIp") String clientIp, @Param("post") Post post);
22+
}

0 commit comments

Comments
 (0)