在同一会话中执行来自不同活动的多个请求

Posted

技术标签:

【中文标题】在同一会话中执行来自不同活动的多个请求【英文标题】:Do multiple requests in the same session from different Activities 【发布时间】:2021-12-17 02:48:10 【问题描述】:

我最近尝试开发一个 servlet,然后将其连接到我的 android 应用程序,但我无法让它正常工作。 这是我的登录 servlet


@WebServlet(name = "login", value = "/auth/login")
public class AuthUser extends HttpServlet 
    private Gson gson = new Gson();

    public void init() 
        Dao.registerDriver();
    

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException 
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        String id = request.getParameter("id");
        String psw = request.getParameter("psw");

        HttpSession s = request.getSession();
        PrintWriter out = response.getWriter();

        HashMap<String, Object> responseJson = new HashMap<>();
        Student student;

        if(id != null && psw != null) 
            student = FetchFromDB.fetchStudentData(id);

            if (student != null && student.getPassword().equals(psw)) 
                s.setAttribute("username", student.getNumber());
                s.setAttribute("surname", student.getSurname());
                s.setAttribute("role", student.getRole());

                responseJson.put("id", request.getSession().getId());
                responseJson.put("user", student);
                responseJson.put("message", "Logged succesfully");
                out.print(new Gson().toJson(responseJson));
             else 
                responseJson.put("message", "The mail or the username is not correct, please try again");
                out.println(new Gson().toJson(responseJson));
            
         else 
            responseJson.put("message", "The mail or username value is null, check that out");
        
        out.flush();
    

    public void destroy() 
    


我从我的 android 应用程序的登录页面调用这个 servlet,如下所示:

  private void login() throws MalformedURLException 
        RequestQueue queue = Volley.newRequestQueue(this);
        String username = usernameText.getText().toString();
        String psw = passwordText.getText().toString();
        String url = Costants.URL + "auth/login?id="+username+"&psw="+psw+"";

        JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
                url,
                null,
                response -> 

                    Log.d("In onResponse", ""+response);
                    try 
                        Log.d("In callServer", "Object returned: " +response.toString());
                        intent.putExtra("key-username", usernameText.getText().toString());
                        intent.putExtra("key-role", response.getJSONObject("user").getString("role"));
                        intent.putExtra("key-surname", response.getJSONObject("user").getString("surname"));
                        intent.putExtra("key-session-id", response.getString("id"));
                        startActivity(intent);
                     catch (JSONException e) 
                        e.printStackTrace();
                    
                , error -> 
                    VolleyLog.d("In onErrorResponse", "Error: " + error.getMessage());
                    Toast.makeText(getApplicationContext(),
                            error.getMessage(), Toast.LENGTH_SHORT).show();
                );
        // Access the RequestQueue through your singleton class.

        MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjReq);

    

当我单击登录按钮时,它可以工作,因此它与 servlet 通信,并且主要活动按应有的方式启动。 但是当我尝试从我的 MainActivity 进行另一个调用时,servlet 中的会话将无法识别,因此用户显示为未知,这是 mainActivity 的代码。

public class MainActivity extends AppCompatActivity 

    private ActivityMainBinding binding;
    String usernameOfLoggedUser;
    String surnameOfLoggedUser;
    String roleOfLoggedUser;
    String sessionId;
    Bundle extras;
    private UserViewModel viewModel;
    private BookedLessonsViewModel bookedLessonsViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        extras = getIntent().getExtras();
        usernameOfLoggedUser = extras.getString("key-username", "NoValue");
        surnameOfLoggedUser = extras.getString("key-surname", "NoValue");
        roleOfLoggedUser = extras.getString("key-role", "NoValue");
        sessionId = extras.getString("key-session-id", "NoValue");
        showWelcomeToast(usernameOfLoggedUser);
        setViewModelUser(usernameOfLoggedUser, roleOfLoggedUser, surnameOfLoggedUser);
        fetchBookedLessons(usernameOfLoggedUser);
        setupUIElements();
    

    /**
     * Fetch lessons from db and set the model view for the lessons booked
     * @param username
     */
    private void fetchBookedLessons(String username) 
        String url = Costants.URL + "book/bookedLessonsForUser";
        ArrayList<BookedLesson> bookedLessons = new ArrayList<>();
        CustomRequest jsonCustomReq = new CustomRequest(
                Request.Method.GET,
                url,
                null,
                sessionId,
                new Response.Listener<JSONObject>() 
                    @Override
                    public void onResponse(JSONObject response) 
                            Log.d("in onResponse", response.toString());
//                        int i = 0;
//                        try 
//                            JSONArray reservations = response.getJSONArray("reservations");
//                            while(i < reservations.length()) 
//                                JSONObject reservation = reservations.getJSONObject(i);
//                                String idUser = reservation.getString("idUser");
//                                String idTeacher = reservation.getString("idTeacher");
//                                String subject = reservation.getString("nameSubject");
//                                String day = reservation.getString("day");
//                                String slot = reservation.getString("slot");
//                                String status =reservation.getString("status");
//
//                                BookedLesson bookedLesson = new BookedLesson(idUser, idTeacher, slot, subject, day, status);
//                                bookedLessons.add(bookedLesson);
//                                i++;
//                            
//                         catch (JSONException e) 
//                            e.printStackTrace();
//                         finally 
//                            setViewModelLessons(bookedLessons);
//                        
                    
                ,
                new Response.ErrorListener() 
                    @Override
                    public void onErrorResponse(VolleyError error) 

                    
                
        );
        MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonCustomReq);
    

    private void showWelcomeToast(String username) 
        Toast toast = Toast.makeText(getApplicationContext(), "You are logged as: " + username, Toast.LENGTH_SHORT*2);
        toast.show();
    


    @Override
    protected void onResume() 
        super.onResume();
        fetchBookedLessons(usernameOfLoggedUser);
    

    private void setupUIElements() 
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        BottomNavigationView navView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(binding.navView, navController);
    

    /**
     * Set the model view for the user so that every fragment has the data for the logged user
     * @param usernameOfLoggedUser
     * @param roleOfLoggedUser
     * @param surnameOfLoggedUser
     */
    private void setViewModelUser(String usernameOfLoggedUser, String roleOfLoggedUser, String surnameOfLoggedUser) 
        viewModel = new ViewModelProvider(this).get(UserViewModel.class);

        viewModel.setUser(usernameOfLoggedUser);
        viewModel.setRole(roleOfLoggedUser);
        viewModel.setSurname(surnameOfLoggedUser);
        viewModel.getUser().observe(this, username -> 
            Log.d("In onCreate", "Share data: " + username);
        );
    

    /**
     * Pass the array fetched and set the model view for the lessons
     * @param lessons
     */
    private void setViewModelLessons(ArrayList<BookedLesson> lessons) 
        bookedLessonsViewModel = new ViewModelProvider(this).get(BookedLessonsViewModel.class);

        bookedLessonsViewModel.setBookedLessons(lessons);

        bookedLessonsViewModel.getBookedLessons().observe(this, bookedLessons -> 
            Log.d("In getBookedLessons", "Lessons: " + bookedLessons.size());
        );
    

但我得到这个值作为回报:

-26 13:48:47.053 12225-12225/com.example.bookinglessons D/in onResponse: "message":"you're not logged"

如果您知道发生了什么,那将非常有帮助,在此先感谢。

【问题讨论】:

【参考方案1】:

我找到了解决此类问题的方法。 您只需在第一个 Activity(在我的例子中为 MainActivity)的 onCreate 中添加这些行。

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

这解决了我的问题并维持了会话。

【讨论】:

以上是关于在同一会话中执行来自不同活动的多个请求的主要内容,如果未能解决你的问题,请参考以下文章

浅析PHP的会话技术

来自多个来源的 CORS

PHP面试 PHP基础知识 八(会话控制)

C#定时器接收定时发送和处理接收socket异步通信,接收值放在静态变量里,有时候收到的数据不完整。

Django会话竞争条件?

Apache同源请求阻塞