Analysis of the Spring MVC Principle

发布于:2023-01-20 ⋅ 阅读:(13) ⋅ 点赞:(0) ⋅ 评论:(0)

Introduction  

Spring MVC framework is one of the most famous and popular frameworks in Java programming. As a professional programmer, it is crucial to understand the principle behind it. This tutorial will briefly introduce Spring MVC and try to replicate the whole framework with POJO Java code. Let's do it!

Components of Spring MVC

Before diving into the concept of MVC, we need first to understand what is MVC:

M(Model): model contains the data of an application that can be transferred within different parts of the MVC system.

C(Controller): the controller is the logic or "brain" of the whole system. We will use some simple servlets to replicate the function of the Spring controller.

V(view): the view represents certain formats that will appear in clients' browsers. Current frequently used view formats are the Jsp and Thymeleaf etc.

Here below is a picture describing what Spring MVC framework looks like;

                               picture source: https://www.javatpoint.com/spring-mvc-tutorial

Configuration using pure Java

The first step is to set up proper Maven dependencies. Basically, what we need is Servlet, Tomcat and primary Spring context.

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.7.RELEASE</version>
</dependency>
 <dependency>
            <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>9.0.36</version>
        </dependency>

After adequately inserting our dependencies, we will handle crucial components in this project. Here, we first need to establish our tomcat setting:

public class MainServer {

    private ApplicationContext applicationContext =
            new AnnotationConfigApplicationContext(ApplicationConfig.class);

    public MainServer(){
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        tomcat.getConnector();

        Context context = tomcat.addContext("",null);

        try {
            List<Class> list = ServletUtil.getClasses("com.project.servlet");
            for (Class  c : list){
                if(c.isAnnotationPresent(ServletObj.class)){
                    // To obtain objects that are annotated with our own @ServletObj
                    ServletObj servletObj = (ServletObj)c.getAnnotation(ServletObj.class);
                    this.registerServlet(context,c,servletObj.url());
                }
            }
            tomcat.start();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // define a method to register servlet 
    private void registerServlet(Context context,Class servletClass,String urlPath) throws Exception {
        Wrapper servlet = Tomcat.addServlet(
                context,
                servletClass.getSimpleName(),
                (Servlet) applicationContext.getBean(servletClass));
        servlet.setLoadOnStartup(1);
        servlet.addMapping(urlPath);
    }

    public static void main(String[] args) {
        new MainServer();
    }
}

First of all, the tomcat port is necessary. Then a context is added for this tomcat. To make things easier, we used a custom annotation called "@ServletObj" to identify which class is the servlet we want to add to our dispatcher. Here is the code of our ServletObj annotation using reflection.

public class ServletUtil {

    // scan the name of packages within typed packageName 
    public static List<Class> getClasses(String packageName){
        List<Class> list = new ArrayList<>();
        // obtain packages' name and replace with the name we want
        String packageDirName = packageName.replace(".","/");
        // obtain full URL
        try {
            URL url = Thread.currentThread().getContextClassLoader()
                    .getResources(packageDirName).nextElement();
            String filePath = URLDecoder.decode(url.getFile(),"utf-8");
            // obtain new object through filepath
            File dirFile = new File(filePath);
            String[] classFiles = dirFile.list();
            for(String f : classFiles) {
                if(f.endsWith(".class")){
                    String fileName = f.substring(0,f.lastIndexOf(".class"));
                    Class c = Class.forName(packageName + "." + fileName);
                    list.add(c);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

}

The ServletUtil class displays how we can scan through the name of our package and obtain all classes underneath it. In this tutorial, we added servlets to our tomcat context and accessed static resources. For our Spring dispatch configuration, we will leave it to the following tutorial. I can't wait to see you next time!