0

我有一个与逻辑相关的问题而不是技术,这是一个场景,(我使用的是 Spring + Hibernate)

我需要从数据库中读取一些数据以在每次获取请求时返回页面,但我认为这里有一些技巧,如果使用某些脚本有人非常频繁地重新加载页面,这将导致对服务器的多次调用,为此我想读取数据并将它们放入全局变量或类变量中,这样做我最终会编写非常奇怪的代码,许多全局变量和愚蠢的方式来给它们初始值,例如变量 user-status 这是我给出的字节类型变量 - 2 作为初始值,这样我的内部逻辑就可以理解数据库中没有为这个变量设置任何值,下面是我的代码

    @Controller
    /* @Secured("hasRole('ROLE_USERS')") */
    @RequestMapping("member")
    public class ApplyRoles {

        @Autowired
        private UserInformationForAccessApplication checkUserStatus;

        // we will initialize variables to avoid auto-initialize by constructor
        private byte userStatus = Constant.IntializationOfGlobalVariable.GLOBALINIT,
                requesttype = Constant.IntializationOfGlobalVariable.GLOBALINIT,
                access = Constant.IntializationOfGlobalVariable.GLOBALINIT;

        Map<String, Object> accessnrole;
        Map<String, String> country;
        Map<String, String> roleArray;

        @Autowired
        StudentEnrollmentApplication enrollmentApplication;

        @Autowired
        SystemProperties systemProperties;

        @Autowired
        EmployeeEnrollmentApplicationResume employeeEnrollmentApplicationResume;

        @Autowired
        AccessEnrollmentProcessing accessEnrollmentProcessing;

        private String role = Constant.IntializationOfGlobalVariable.ROLENOTSET,
                fname, lname;

        @RequestMapping(value = "/user", method = RequestMethod.GET)
        public String checkingUserStatus(Model model, HttpSession session,
                Authentication authentication) {

            String sessionemail = "yashprit@gmail.com";// (String) session
            // .getAttribute(Constant.SessionAttributes.LOGGEDINUSER);

            // first check global value, if found set than don't fetch from database
            if (userStatus == Constant.IntializationOfGlobalVariable.GLOBALINIT) {
                // get user status from MySQL Database
                userStatus = checkUserStatus.checkStatus(sessionemail).get(0);
                if (!(userStatus == Constant.UserRoleApplicationStatus.NOTAPPLIED)) {
                    access = checkUserStatus.checkStatus(sessionemail).get(1);
                    model.addAttribute(Constant.SystemName.ACCESS, access);
                }
            }

            if (!(userStatus >= Constant.UserRoleApplicationStatus.NOTAPPLIED || userStatus <= Constant.UserRoleApplicationStatus.REJECTED)) {
                model.addAttribute("error", "User status is not avaible");
                return "redirect:error/pagenotfound";
            } else if (userStatus == Constant.UserRoleApplicationStatus.NOTAPPLIED) {
                if (requesttype == Constant.IntializationOfGlobalVariable.GLOBALINIT) {
                    // get request type from MongoDB database
                    requesttype = checkUserStatus.getRequestType(sessionemail);
                }

                if (!(requesttype == Constant.RequestType.NORMALEBIT || requesttype == Constant.RequestType.INVITEBIT)) {
                    model.addAttribute("error",
                            "Facing Technichal Issue, Please try again");
                    return "redirect:error/pagenotfound";
                }

                if (requesttype == Constant.RequestType.INVITEBIT) {
                    if (!(Byte.parseByte((String) accessnrole
                            .get(Constant.SystemName.ACCESS)) == Constant.Access.USERBIT)) {
                        accessnrole = checkUserStatus
                                .getAccessAndRole(sessionemail);
                    }

                    if (accessnrole.get(Constant.SystemName.ACCESS).equals(
                            Constant.Database.ERRORMESSAGE)
                            || accessnrole.get(Constant.SystemName.ROLE).equals(
                                    Constant.Database.ERRORMESSAGE)) {

                        model.addAttribute("error",
                                "Facing Technichal Issue, Please try again");
                        return "redirect:error/pagenotfound";
                    }

                    model.addAttribute(Constant.SystemName.ACCESSNROLE, accessnrole);
                    model.addAttribute(Constant.SystemName.REQUESTTYPE, requesttype);
                }
            }

            model.addAttribute(Constant.SystemName.USERSTATUS, userStatus);


            return "member/user";

        }
}

to avoid global variable i thought of suing cookies, because I don't want to call database on every page reload in same session, once its loaded for a session than I don't have to call to database.

Anything that can help to to redesign above part of code is much appreciated

thanks

4

2 回答 2

1

There are really 2 things that you are considering, and correctly me if I'm wrong, but:

  1. Caching on the server (in your Java application) to avoid doing a database lookup multiple times for the same data.
  2. Avoid the client (browser) from sending multiple requests to the server.

The first can be resolved using caching which is available in spring uses annotations on any given method. The documentation is available here.

The second is a bit more tricky and I' leave it for now unless you discover a performance problem. It's again possible to do in Spring and takes advantage of the HTTP protocol and caching controls available in the HTTP header to inform the browser how long to cache responses.

于 2013-03-06T20:54:58.567 回答
0

What you are thinking about is called a "cache". It is a standard Computer Science way of doing things and they have been doing research on how to use caches for as long as there have been computers.

You might want to go do some reading on the subject. I found this one by Googling "cache tutorial java" http://javalandscape.blogspot.com/2009/01/cachingcaching-algorithms-and-caching.html

In simplest terms (a one item cache) what you want is to store some data object that you recently took some time to come up with. But you also have to have some sort of identifier so you can tell if the next request is asking for the same data. If it isn't, you have to do all the work over. If it is the same data, you just return it again.

So the algorithm works something like this in this simple case:

if (storedData != null && storedRequestInfo == userRequest.requestInfo) {
    return storedData;
}

storedData = youCalculateTheRequestedData();
storedRequestInfo = userRequest.requestInfo;

return storedData;

Its not any real programming language, just something to show you how it works.

The requestInfo is whatever comes in with the request that you use to look up your database stuff. You save it in storedRequestInfo after any calculation.

This shows it as returning some data to the user, that's what is in storedData.

It's a simple, one-element cache.

(To expand on this, you can store the storedRequestInfo and storedData in the session and you end up with one of these stored for each user. You can also use a java Map and store a bunch of storedData. The problem is to decide how to limit your memory use. If you store too many of these for each user, you use up too much memory. So you limit how many each user can have either by size or by count. Then you have to decide which one to delete when it gets too big. In the simple case, you always delete, in essence, the stored one and store a new one.

I noticed your comment. ECache is just a big fancy Map in the terms I used above. I don't know if it's naturally session dependent but it can be made that way by adding the session id to the cache key.)

于 2013-03-06T20:54:45.963 回答