Giter Club home page Giter Club logo

cs307proj2's Introduction

CS307Proj2

Basic Information

Names, student IDs, and the lab session

lab session Names student IDs
3 程嘉朗 12111622
3 伍福临 12110411

API specification

  1. MainController.java

    • query

      @GetMapping("/query")
      @ResponseBody
      public List<Users> query()
      • HTTP request type: get
      • Function and return value: return a list of all users, including all the information that needs to be rendered
    • findCurrentUser

      @GetMapping("/current_user")
      @ResponseBody
      public String findCurrentUser(HttpServletRequest request)
      • HTTP request type: get
      • Function and return value: return the current user name
    • findCurrentUserId

      @GetMapping("/current_userId")
      @ResponseBody
      public long findCurrentUserId(HttpServletRequest request)
      • HTTP request type: get
      • Function and return value: return the current user ID
    • login

      @GetMapping("/login")
      @ResponseBody
      public String login(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get
      • Function and return value: return whether the user has login
    • login

      @PostMapping("/login")
      @ResponseBody
      public String login(@RequestBody Users user, Model model, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post

      • Function and return value: return whether the user input valid username and password

    • signup

      @GetMapping("/signup")
      @ResponseBody
      public String signup(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get
      • Function and return value: return whether the user need to login or signup
    • signup

      @PostMapping("/signup")
      @ResponseBody
      public Map<String, String> register(@RequestBody Users user, HttpServletResponse response)
      • HTTP request type: post

      • Function and return value: return whether username, password, phone meet the reqirement

    • logout

      @DeleteMapping("/logout")
      @ResponseBody
      public String logout(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: delete

      • Function and return value: delete the cookies and return successfuly logout

  2. usercontroller

    • findPostInPage, findShareInPage , findLikeInPage, findFavoriteInPage

      @GetMapping("/homepage/post")
      public List<Posts> findPostInPage(@RequestParam("lastPostId") Long lastPostId, @RequestParam("limit") int limit, HttpServletRequest request, HttpServletResponse response)
          
      @GetMapping("/homepage/share")
      public List<Posts> findShareInPage(@RequestParam("lastPostId") Long lastPostId, HttpServletRequest request, @RequestParam("limit") int limit, HttpServletResponse response)
          
      @GetMapping("/homepage/like")
      public List<Posts> findLikeInPage(@RequestParam("lastPostId") Long lastPostId, HttpServletRequest request, @RequestParam("limit") int limit, HttpServletResponse response)
          
      @GetMapping("/homepage/favorite")
      public List<Posts> findFavoriteInPage(@RequestParam("lastPostId") Long lastPostId, HttpServletRequest request, @RequestParam("limit") int limit, HttpServletResponse response)
      • HTTP request type: get

      • Request Parameter:

        lastPostId:The ID of the last post

        limit: Limit how many the latest posts you can get

      • Function and return value: return the latest limit posts

    • findHotPostInPage

      @GetMapping("/homepage/hotpost")
      public List<Posts> findHotPostInPage(@RequestParam("lastPostId") Long lastPostId, @RequestParam("limit") int limit, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get

      • Request Parameter:

        lastPostId:The ID of the hottest post

        limit: Limit how many the hottest posts you can get

      • Function and return value: return the hottest limit posts

    • searchPost

      @PostMapping("/homepage/search")
      public List<Posts> searchPost(@RequestBody ArrayList<Filter> filters, HttpServletRequest request)
      • HTTP request type: post

      • Request Body: a list of filters(self-define objects), indicating restrictions for searching the posts

      • Function and return value: return the posts that meet the restrictions

    • findYourPostInPage, findMyPost

      @GetMapping("/homepage/yourPost")
      public List<Posts> findYourPostInPage(@RequestParam("lastPostId") Long lastPostId, HttpServletRequest request, @RequestParam("limit") int limit, HttpServletResponse response)
          
      @GetMapping("/user/homepage/post")
      public List<Posts> findMyPost(@RequestParam long senderId, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get

      • Response data format: json

      • Request Parameter:

        lastPostId:The ID of the your last post

        limit:Limit how many your latest posts you can get

      • Function and return value: return your latest limit posts

    • findMyReplyPost

      @GetMapping("/user/homepage/yourReplyPost")
      public List<Posts> findMyReplyPost(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get

      • Response data format: json

      • Function and return value: return the your Reply posts

    • sendPosts

      @PostMapping("/user/homepage/post")
      public int sendPosts(@RequestBody Posts posts, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post

      • Request Body:

      • Function and return value: Post articles and return 1 if succeeds

    • uploadPic

      @PostMapping("/Files/users/{userId}")
      public void uploadPic(HttpServletRequest request, HttpServletResponse response, @RequestBody MultipartFile file, @PathVariable long userId)
      • HTTP request type: post

      • Request Body: a file(which can be video or picture)

      • Path Variable: a subdirectory indicating that the files belong to the specified user

      • Function: Upload picture when post

    • findMyReplies

      @GetMapping("/user/homepage/replies")
      public List<Replies> findMyReplies(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get
      • Function and return value: return all my replies
    • findReplyByPost

      @GetMapping("/user/homepage/post/replies")
      public List<Replies> findReplyByPost(@RequestParam("id") Long postId, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get

      • Request Parameter:

        id: The corresponding post id

      • Function and return value: return the reply of the corresponding post id

    • sendReplies

      @PostMapping("/user/homepage/replies")
      public int sendReplies(@RequestBody Replies replies, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post

      • Request Body: All information need to store in replies

      • Function: Send replies and return 1 if succeeds.

    • starReply

      @PostMapping("/user/homepage/replies/star")
      public int starReply(@RequestParam("replyId") long replyId, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post

      • Request Parameter: the id of the corresponding reply

      • Function: Star the corresponding reply and return 1 if succeeds.

    • likePost

      @PostMapping("/user/like")
      public String likePost(@RequestBody LikePostWrapper lpw, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post

      • Request Body:

      • Function: Like post

    • unLike

      @DeleteMapping("/user/like")
      public int unLike(@RequestParam("postId") long postId, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: delete
      • Request Param: the id of the corresponding liked post
      • Function and return value: un like the corresponding post, return 1 if succeed.
    • checkLikes

      @GetMapping("/user/like")
      public List<Posts> checkLikes(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get
      • Function: Get the liked posts
    • favorPost

      @PostMapping("/user/favor")
      public String favorPost(@RequestBody FavorPostWrapper fpw, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post

      • Request Body: the postId which is favored

      • Function: Favorite post

    • unFavorite

      @DeleteMapping("/user/favorite")
      public int unFavorite(@RequestParam("postId") long postId, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: delete
      • Request Param: the id of the corresponding favorited post
      • Function and return value: un favorite the corresponding post, return 1 if succeed.
    • checkFavors

      @GetMapping("/user/favor")
      public List<Posts> checkFavors(HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: get
      • Function and return value: return the favorited posts
    • sharePost

      @PostMapping("/user/share")
      public String sharePost(@RequestBody SharePostWrapper spw, HttpServletRequest request, HttpServletResponse response)
      • HTTP request type: post
      • Request Body: the postId which is shared
      • Function and return value: Share post, return success
    • unSharePost

      @DeleteMapping("/user/share")
      public String unSharePost(@RequestParam("postId") long originalPostId, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: delete
      • Request Param: the id of the corresponding post
      • Function and return value: Revoke sharing the corresponding post and return success
    • checkShares

      @GetMapping("/user/share")
      public List<Posts> checkShares(HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: get
      • Function and return value: return your shared posts
    • findShareIds

      @GetMapping("user/share/ids")
      public List<Long> findShareIds(HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: get
      • Function and return value: return the id of your shared posts
    • follow

      @PostMapping("/user/follow")
      public int follow(@RequestBody FollowUserWrapper fuw, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: post
      • Request Body: the followed userid
      • Function and return value: Follow users and return 1 if succeed
    • unfollow

      @DeleteMapping("/user/follow")
      public int unfollow(@RequestParam("followigid") long followigid, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: delete
      • Request Param: the corresponding id of the followed users
      • Function and return value: un follow the corresponding users, return 1 if succeed
    • findFollow

      @GetMapping("/user/follow")
      public List<Users> findFollow(HttpServletRequest request, HttpServletResponse response, @RequestParam("offset") long offset,
      @RequestParam("limit") long limit)
      
      • HTTP request type: get

      • Request Param:

        offest: how many users has been got

        limit: how many users are needed in this request

      • Function and return value: return your followed users

    • findFollowIds

      @GetMapping("user/follow/ids")
      public List<Long> findFollowIds(HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: get
      • Function and return value: return the id of your followed users
    • shield

      @PostMapping("/user/shield")
      public int shield(@RequestBody ShieldUserWrapper fuw, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: post
      • Request Body: the id you need to shield
      • Function and return value: Shield users, return 1 if succeed
    • unshield

      @DeleteMapping("/user/shield")
      public int unshield(@RequestParam("shieldid") long shieldid, HttpServletRequest request, HttpServletResponse response)
      
      • HTTP request type: delete
      • Request Param: the corresponding id of the shielded users
      • Function and return value: un shield the corresponding users, return 1 if succeed

Advance Requirement

  1. Complete the project using opengauss database (task 1)

    Install opengauss:

  2. Enhance the usability of the APIs (task 2)

    • Speak anonymously

      • We allow users post or comment anonymously.

      • When users post or comment or reply comment, they can choose public or anonymous by a switch

      • Once it is anonymous, others users can't see who send the post or the comment.

      How to achieve anonymity?

      • Actually, in the database, the true information of poster or replier are still be registered. But we record whether it is anonymous.

        post anonymously

        @Insert("insert into posts(title, content, postingtime, authorid, city, country, senderid, anonymous, originpostid, filePath, issenderanonymous) " +"values (#{title}, #{content}, #{postingTime}, #{authorId}, #{city}, #{country}, #{senderId}, #{anonymous}, #{postId}, #{filepath}, #{issenderanonymous}) returning postid")

        anonymous is used to record the author of the post whether is anonymous or not

        issenderanonymous is used to record the sender of the post whether is anonymous or not

        when we need to show the post, we do Query from database, and then judge the two attributes to render the front-end interface.

        <el-tag type="success" style="margin-right: 10px">{{!this.post.anonymous ? post.senderName : "anonymous"}}</el-tag>
        <el-tag type="success" style="margin-right: 10px">{{!this.post.issenderanonymous ? post.authorName 

        comment anonymously

        @Insert("insert into replies(toreplyid, topostid, content, stars, authorid, anonymous, orginalanonymous) " + "VALUES (#{toreplyid}, #{topostid}, #{content}, #{stars}, #{authorid}, #{anonymous}, #{orginalanonymous})")

        anonymous is used to record the author of the reply whether is anonymous or not

        orginalanonymous is used to to record the author of the original reply the author replied whether is anonymous or not

        when we need to show the reply, we do Query from database, and then judge the two attributes to render the front-end interface.

        <el-tag type="success" style="margin-right: 10px">{{item.anonymous ? "anonymous" : item.authorName}}</el-tag>
        <el-tag type="success" style="margin-right: 10px" v-if="item.toUserName">{{item.orginalanonymous ? "anonymous" : item.toUserName }}</el-tag>
    • picture and video upload

      • use el-upload component in element-ui

      • bind a reference upload to the component

        <el-upload ref="upload"></el-upload>
      • specific the location(the static resourse directory of the springboot)

        <el-upload 
        	ref="upload"
        	:action= '`http://localhost:9090/Files/users/${this.userId}`'>
        </el-upload>
      • use function submit() to upload the source

        this.$refs.upload.submit();
      • store the filepath in the database

      • when get the posts from the back-end, the from-end also get the file path, hence it can access the file and show it

    • shield

      • we allow the users to shield other users

      • When user want to shield other users, search it in all users and then click the switch the state of shield

      • There is a table to record other users the user have shield

        @Insert("insert into shieldby(userID, shieldID) values(#{userid}, #{shieldigid});")
      • when we need to show the post, we do Query from database, filter authors and senders who are not shield by current users.

        @Select("select p.*, u.username authorname, v.username sendername \n" +
                    "from posts p join users u on p.authorid = u.userid join users v on p.senderid = v.userid \n" +
                    "where postid <= #{lastPostId} and postid > #{lastPostId} - #{limit} \n" +
                    "and u.userID not in (select shieldID from shieldby where userID = #{userid})\n" +
                    "and v.userID not in (select shieldID from shieldby where userID = #{userid})\n" +
                    "order by p.postid desc;")

        Here we only show the code of homepage where we show the posts. Actually, other pages like like posts or share posts or hot posts are as the same as the codes beyond.

    • Hot search list

      • we show the 50th hottest posts in the hot post page

      • we define a formula to represent the hot: hot = comments * 1 + likes * 2 + favorites * 3 + shares * 4

      • when we need to get the hot posts, we filter in the query sentences.

        @Select("select p.*, u.username authorname, v.username sendername, " +
                    "(SELECT COUNT(*) FROM replies c WHERE c.topostid = p.postid) +\n" +
                    "(SELECT COUNT(*) FROM likes l WHERE l.postid = p.postid) * 2 +\n" +
                    "(SELECT COUNT(*) FROM favorites f WHERE f.postid = p.postid) * 3 +\n" +
                    "(SELECT COUNT(*) FROM shares s WHERE s.postid = p.postid) * 4 AS hot\n" +
                    "from posts p join users u on p.authorid = u.userid join users v on p.senderid = v.userid " +
                    "and u.userID not in (select shieldID from shieldby where userID = #{userid})\n" +
                    "and v.userID not in (select shieldID from shieldby where userID = #{userid})\n" +
                    "order by hot desc;")

        We get the hot of the post and rank the display in descending order based on the hot of the post

      • When we like or unlike and so on, we change the data of the front-end, then refresh the page, get hot posts from back-end again, complete the change of hot. Here is an example below.

        toggleShare() {
            ...
            this.post.hot += 4;    
        }
        toggleUnShare(){
            ...
            this.post.hot -= 4; 
        }
    • Multi-parameter search function

      • We allow the users to add plenty constraints as long as they want.

      • We can seach data by: author, sender, postingTime, title, content

      • title and contentsupport fuzzy search

      How to seach the data by such restrictions?

      • back-end can get a series of restriction in List<T>

      • use .xml configuration file to configurate SQL statement, foreach is use to iterate the List

        <foreach collection='author' item='item' index='index' separator=' OR '>
        	authorname = #{item}
        </foreach>
      • To see more, please refer to the findPostsByFilter in PostMapper.java

    • Record the user login status

      If the user does not login, webpage will be redirected to localhost:8080/login even if he want to access the localhost:8080/user/homepage

      • create CookieManager in util package, it store all static methods we use to manage the cookies

      • get cookies from HttpServletRequest request

        Cookie[] cookies = request.getCookies();
      • add/update the cookie to 1 hour

        cookie.setMaxAge(60*60);
        cookie.setPath("/"); 
        response.addCookie(cookie);
      • delete the cookie

        cookie.setMaxAge(0);
        cookie.setPath("/"); 
        response.addCookie(cookie);
    • IP analysis

      The city of a post and country should not detemine by user, but how to get the city of the posting place?

      • add dependency in pom.xml

        <dependency>
            <groupId>com.maxmind.geoip2</groupId>
            <artifactId>geoip2</artifactId>
            <version>2.13.1</version>
        </dependency>
      • Search the ip in the front-end and wrap it in the data send to the back-end

        axios.get('https://api.ipify.org?format=json',{withCredentials: false}
        )
        .then(response => {
            ip = response.data.ip;
        }
      • install Geaolite2-city.mmdb

      • use Geaolite2-city.mmdb to map an ip to a city

  3. Technology stack introduction: (task 3 & 4 & 6)

    • Backend: springboot
    • Front end: vue2+vuex+vue-router+axios
    • Component library: element-ui
    • Front-end and back-end connection test: swagger 2
    • Connection pool: druid
    • ORM: Mybatis-plus
    • POJO to json: Jackson

    advantage:

    1. Separation of front-end and back-end development: the back-end receives and verifies the front-end request, and then returns the data (Restful) required by the front-end in json format, and renders after the front-end gets the data.
    2. springboot: Adopting the method of convention over configuration, it provides developers with a very suitable environment for web development. At the same time, based on dependency injection(DI) and inversion of control transfer(IOC), it helps developers manage a series of tasks.
    3. Vue2: Progressive framework, easier to learn than react, two-way data binding, good at making single-page web pages.
    4. druid: The connection pool developed by Alibaba provides monitoring functions to clearly know the working conditions of the connection pool and SQL
    5. Mybatis-plus: On the basis of Mybatis, single-table query is enhanced, and SQL statements are bound through annotations or configuring .xml files
  4. create index: (task 7)

    To enhance the speed of Multi-parameter search function. At the same time, we find the length of the column title in table posts are always much shorter then the content, hence we decide to create index in column title

    CREATE INDEX title_index ON posts (title);
    

cs307proj2's People

Contributors

andychenggg avatar publicclassdemo avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.