Servlet Filters සහ Listeners: Web App එකට වැඩිපුර බලයක්! SC Guide

Servlet Filters සහ Listeners: Web App එකට වැඩිපුර බලයක්! SC Guide

Mastering Servlet Filters and Listeners SC Guide

කොහොමද යාලුවනේ! Tech දන්න, Tech ගැන දැනගන්න කැමති ඔයාලා හැමෝටම අද ගේන ලිපිය ගොඩක් වටිනවා කියලා මට sure. අපි හැමෝම web application develop කරනකොට Servlets පාවිච්චි කරනවනේ. ඒත් සමහර වෙලාවට අපිට ඕන වෙනවා request එකක් එනකොටම ඒක check කරන්න, එහෙම නැත්නම් application එක start වෙනකොටම මොකක් හරි වැඩක් කරන්න. නිකන් හිතන්නකෝ, ඔයාගේ web app එකට එන හැම request එකක්ම log කරන්න ඕනේ, නැත්නම් user කෙනෙක් login කරලාද කියලා බලන්න ඕනේ, එහෙම නැත්නම් application එක start වෙනකොටම database connection එකක් හදාගන්න ඕනේ කියලා. මේ වගේ දේවල් Servlets ඇතුලේ කරන්න ගියොත් වැඩේ අවුල් වෙනවා. Code duplicate වෙනවා, maintain කරන්න අමාරු වෙනවා. මේ වගේ අවුල් නැතුව වැඩේ ලස්සනට කරගන්න අපිට තියෙන සිරාම option එක තමයි Servlet Filters සහ Listeners කියන්නේ. අද අපි මේ ගැන මුල ඉඳන්ම සිංහලෙන් සරලව කතා කරමු.

Servlet Filters කියන්නේ මොනවද?

හරි, මුලින්ම බලමු මේ Servlet Filters කියන්නේ මොනවද කියලා. සරලව කිව්වොත්, Filter එකක් කියන්නේ Servlet එකකට request එකක් එන්න කලින් හෝ Servlet එකෙන් response එකක් යන්න කලින් ඒක අල්ලගෙන මොකක් හරි වැඩක් කරන්න පුළුවන් යාන්ත්‍රණයක්. මේක හරියට Security Checkpoint එකක් වගේ. request එක යන්න කලින් filter එකෙන් check කරනවා, modify කරනවා, එහෙම නැත්නම් සම්පූර්ණයෙන්ම නවත්තලත් දාන්න පුළුවන්.

Filters පාවිච්චි කරන්නේ මොනවටද?

  • Logging: හැම request එකක්ම log කරන එක.
  • Authentication/Authorization: User කෙනෙක් system එකට login කරලාද, එයාට මේ page එක බලන්න අවසර තියෙනවාද කියලා බලන එක.
  • Data Compression: Response එක browser එකට යවන්න කලින් compress කරන එක.
  • Character Encoding: Input request වල Character Encoding එක manage කරන එක.
  • Input Validation: User ගෙන් එන data validate කරන එක.

Filter එකක් හදන්නේ කොහොමද?

Filter එකක් හදනවා කියන්නේ javax.servlet.Filter interface එක implement කරන එක. මේ interface එකේ methods තුනක් තියෙනවා:

  1. init(FilterConfig filterConfig): Filter එක initialize වෙනකොට call වෙනවා.
  2. doFilter(ServletRequest request, ServletResponse response, FilterChain chain): හැම request එකකටම call වෙන main method එක.
  3. destroy(): Filter එක destroy වෙනකොට call වෙනවා.

අපි පොඩි Log Filter එකක් හදලා බලමු.

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class RequestLoggerFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("RequestLoggerFilter initialized.");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        long startTime = System.currentTimeMillis();
        System.out.println("Incoming request URL: " + ((HttpServletRequest) request).getRequestURL());

        // request එක ඊළඟ filter එකට, නැත්නම් Servlet එකට යවනවා
        chain.doFilter(request, response);

        long endTime = System.currentTimeMillis();
        System.out.println("Request processed in " + (endTime - startTime) + "ms.");
    }

    @Override
    public void destroy() {
        System.out.println("RequestLoggerFilter destroyed.");
    }
}

මේක deploy කරන්න web.xml එකේ මෙහෙම configure කරන්න පුළුවන්. (අනිවාර්යයෙන්ම annotation වලින් කරන්නත් පුළුවන්, ඒත් මුලින්ම මේ විදිහට බලමු.)

<filter>
    <filter-name>requestLogger</filter-name>
    <filter-class>RequestLoggerFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>requestLogger</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

මතක තියාගන්න, <url-pattern>/*</url-pattern> කියන්නේ හැම URL එකකටම මේ filter එක apply වෙනවා කියන එක.

Filter Chain එකේ බලය

Filter එකක් විතරක් නෙවෙයි, අපිට එකම request එකකට Filter ගොඩක් apply කරන්න පුළුවන්. මේක තමයි Filter Chain එක කියන්නේ. request එකක් එනකොට, ඒක Filter Chain එකේ තියෙන හැම filter එකක් හරහාම යනවා, හැබැයි අපි chain.doFilter() කියන method එක call කරනවා නම් විතරයි.

chain.doFilter() කරන දේ:

  • chain.doFilter() call කරාම, request එක ඊළඟ filter එකට යනවා.
  • Chain එකේ ඊළඟට filter එකක් නැත්නම්, request එක අදාළ Servlet එකට යනවා.

Authentication Filter එකක්:

අපි බලමු user කෙනෙක් login කරලාද කියලා check කරන Filter එකක්.

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebFilter(urlPatterns = "/secure/*")
public class AuthenticationFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("AuthenticationFilter initialized.");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        HttpSession session = req.getSession(false); // false කියන්නේ session එකක් නැත්නම් අලුතින් හදන්නේ නෑ.

        if (session != null && session.getAttribute("loggedInUser") != null) {
            // User login කරලා, request එක ඊළඟට යවනවා
            System.out.println("User is authenticated. Proceeding...");
            chain.doFilter(request, response);
        } else {
            // User login කරලා නෑ, login page එකට redirect කරනවා
            System.out.println("User not authenticated. Redirecting to login page.");
            res.sendRedirect(req.getContextPath() + "/login.html");
        }
    }

    @Override
    public void destroy() {
        System.out.println("AuthenticationFilter destroyed.");
    }
}

මේ filter එකේ අපි @WebFilter(urlPatterns = "/secure/*") annotation එක පාවිච්චි කරලා තියෙනවා. ඒ කියන්නේ /secure/ වලින් පටන් ගන්න හැම URL එකකටම මේ filter එක apply වෙනවා. මේ විදිහට annotations පාවිච්චි කරන එක web.xml එකට වඩා ලේසියි.

Servlet Listeners කියන්නේ මොනවද?

දැන් අපි බලමු Servlet Listeners කියන්නේ මොනවද කියලා. Filters request/response events වලට ප්‍රතිචාර දක්වනවා වගේම, Listeners web application lifecycle events වලට ප්‍රතිචාර දක්වනවා. මේවා application එක start වෙනකොට, destroy වෙනකොට, session එකක් create වෙනකොට, attribute එකක් add වෙනකොට වගේ දේවල් වලට call වෙනවා.

Listeners වර්ග:

Listeners වර්ග ගොඩක් තියෙනවා. මේවා application context, session, request වගේ විවිධ scopes වල සිදුවීම් වලට සවන් දෙනවා:

  • ServletContextListener: Web application එක start වෙනකොට සහ destroy වෙනකොට.
  • ServletRequestListener: Request එකක් create වෙනකොට සහ destroy වෙනකොට.
  • HttpSessionListener: Session එකක් create වෙනකොට සහ destroy වෙනකොට.
  • ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener: Attribute එකක් add, replace, remove වෙනකොට.

Listener එකක් හදන්නේ කොහොමද?

අපි පොඩි ServletContextListener එකක් හදලා බලමු. මේක application එක start වෙනකොට database connection pool එකක් initialize කරන්න වගේ දේවල් වලට පාවිච්චි කරන්න පුළුවන්.

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Web application started! Initializing resources...");
        // මෙතනදී database connection pool එකක්, configuration files load කරන එක වගේ දේවල් කරන්න පුළුවන්.
        sce.getServletContext().setAttribute("appName", "MyAwesomeWebApp");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Web application shutting down! Cleaning up resources...");
        // මෙතනදී database connections close කරන එක, resources release කරන එක වගේ දේවල් කරන්න පුළුවන්.
        sce.getServletContext().removeAttribute("appName");
    }
}

මේ Listener එක deploy කරන්න web.xml එකේ මෙහෙම configure කරන්න පුළුවන්, එහෙම නැත්නම් @WebListener annotation එක පාවිච්චි කරන්න පුළුවන්.

<listener>
    <listener-class>AppContextListener</listener-class>
</listener>

මේ Listener එක හදලා Deploy කරාම, web application එක start වෙනකොට contextInitialized method එකත්, application එක stop කරනකොට contextDestroyed method එකත් automatically call වෙනවා. මේක ගොඩක්ම ප්‍රයෝජනවත් වෙනවා application-wide resources handle කරනකොට.

Filters සහ Listeners කොහොමද එකට වැඩ කරන්නේ?

Filters සහ Listeners කියන්නේ එකිනෙකට වෙනස් concepts දෙකක් වුණත්, ඒවා web application එකක ක්‍රියාකාරීත්වය වැඩිදියුණු කරන්න එකට පාවිච්චි කරන්න පුළුවන්.

  • Filters: Request-specific tasks වලට, එනම් request එකක් එනකොට හෝ යනකොට ඒක analyze කරන්න, modify කරන්න, validate කරන්න, security check කරන්න වගේ දේවල් වලට.
  • Listeners: Application-wide lifecycle events වලට, එනම් application එක start/stop වෙනකොට, session එකක් create/destroy වෙනකොට වගේ දේවල් වලට.

උදාහරණයක් විදිහට, ඔබට Listener එකක් පාවිච්චි කරලා application එක start වෙනකොට database connection pool එකක් initialize කරන්න පුළුවන්. ඊට පස්සේ Filter එකක් පාවිච්චි කරලා හැම request එකකටම ඒ connection pool එකෙන් connection එකක් අරගෙන වැඩේ ඉවර වුණාම ආපහු release කරන්න පුළුවන්. මේකෙන් resource management එක ගොඩක් කාර්යක්ෂම වෙනවා.

නිගමනය:

ඉතින් යාලුවනේ, අද අපි Servlet Filters සහ Listeners ගැන සවිස්තරාත්මකව කතා කළා. මේවා අපේ web applications වල functionality වැඩිදියුණු කරන්න, code එක clean කරගන්න, සහ maintenance ලේසි කරගන්න ගොඩක් වැදගත් concepts කියලා ඔයාලට පැහැදිලි වෙන්න ඇති. ගොඩක් වෙලාවට experienced developersලා මේ වගේ patterns තමයි පාවිච්චි කරන්නේ robust සහ scalable applications හදන්න.

දැන් ඔයාලත් මේ concepts ඔයාලගේ projects වලට implement කරලා බලන්න. මොකද theory විතරක් මදි, practice කරන එක තමයි වැදගත්ම දේ. මේ ගැන තව මොනවා හරි දැනගන්න ඕන නම්, ප්‍රශ්න තියෙනවා නම්, එහෙම නැත්නම් ඔයාලගේ අදහස් share කරන්න ඕන නම්, අනිවාර්යයෙන්ම පහළ තියෙන comment section එකේ දාන්න. අපි ඊළඟ article එකෙන් හමුවෙමු! පරිස්සමෙන් ඉන්න!