Comparable is for objects with a natural ordering. The object itself knows how it is to be ordered.If any class implement Comparable interface in Java then collection of that object either List or Array can be sorted automatically by using Collections.sort() or Arrays.sort() method and object will be sorted based on there natural order defined by CompareTo method.

Comparator is for objects without a natural ordering or when you wish to use a different ordering.

Natural ordering is the Ordering implemented on the objects of each class. This ordering is referred to as the class’s natural ordering.For example Strings Natural Ordering is defined in String Class

Comparable
Compares object of itself with some other objects.Comparable overrides compareTo

Employee.java

package com.acme.users;

public class Employee implements Comparable<Employee> {
	public String EmpName;
	public Integer EmpId;
	public Integer Age;
	
	public Employee(Integer pEmpId, String pEmpName, Integer pAge)
	{
		this.EmpName = pEmpName;
		this.EmpId   = pEmpId;
		this.Age     = pAge;
	}
	
	
	public String getEmpName() {
		return EmpName;
	}
	public void setEmpName(String empName) {
		EmpName = empName;
	}
	public Integer getEmpId() {
		return EmpId;
	}
	public void setEmpId(Integer empId) {
		EmpId = empId;
	}
	public Integer getAge() {
		return Age;
	}
	public void setAge(Integer age) {
		Age = age;
	}
	
	@Override
	public int compareTo(Employee arg0) 
	{	
		if(this.getEmpId() == arg0.getEmpId())
			return 0;
		else if (this.getEmpId() > arg0.getEmpId())
			return 1;
		else
			return -1;
	}
}

EmpDashBoard.java

package com.acme.users;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class EmpDashBoard {
	public static void main(String[] args) {

		List<Employee> arrEmpList = new ArrayList();

		Employee objEmp1 = new Employee(101, "Ahmed", 31);
		Employee objEmp2 = new Employee(127, "Mahesh", 24);
		Employee objEmp3 = new Employee(109, "Viparna", 85);
		Employee objEmp4 = new Employee(101, "Abdul", 26);
		Employee objEmp5 = new Employee(104, "Muthu", 23);
		Employee objEmp6 = new Employee(115, "Monalisa", 25);

		arrEmpList.add(objEmp1);

		arrEmpList.add(objEmp2);
		arrEmpList.add(objEmp3);
		arrEmpList.add(objEmp4);
		arrEmpList.add(objEmp5);
		arrEmpList.add(objEmp6);

		System.out.println("Sorted based on Natural Sorting(Emp Id)");
		System.out.println("Before Sorting");
		dispListContent(arrEmpList);
		
		Collections.sort(arrEmpList);
		
		System.out.println("After Sorting");
		dispListContent(arrEmpList);
	}

	public static void dispListContent(List<Employee> parrEmployeeLst) {
		System.out.println(" ");

		System.out.println("EmpId" + " " + "EmpName" + "     " + "Age");
		System.out.println("---------------------------");
		for (Employee object : parrEmployeeLst) {
			System.out.print(object.getEmpId() + "   ");
			System.out.print(object.getEmpName() + "     ");
			System.out.println(object.getAge() + " ");
		}
	}
}

Output

Sorted based on Natural Sorting(Emp Id)

Before Sorting
 
EmpId EmpName     Age
---------------------------
101   Ahmed       31 
127   Mahesh      24 
109   Viparna     85 
101   Abdul       26 
104   Muthu       23 
115   Monalisa    25 

After Sorting
 
EmpId EmpName     Age
---------------------------
101   Ahmed       31 
101   Abdul       26 
104   Muthu       23 
109   Viparna     85 
115   Monalisa    25 
127   Mahesh      24 

Comparator
In some situations, you may not want to change a class and make it comparable. In such cases, Comparator can be used.Comparator overrides compare

Comparator provides a way for you to provide custom comparison logic for types that you have no control over.

In the below Example I have Sorted the Employee class Objects based on Name(EmpNameComparator), Age(EmpAgeComparator) and based on EmpIDName(EmpIdNameComparator)

EmpDashBoard.java

package com.acme.users;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class EmpDashBoard {
	public static void main(String[] args) {

		List<Employee> arrEmpList = new ArrayList();

		Employee objEmp1 = new Employee(101, "Ahmed", 31);
		Employee objEmp2 = new Employee(127, "Mahesh", 24);
		Employee objEmp3 = new Employee(109, "Viparna", 85);
		Employee objEmp4 = new Employee(101, "Abdul", 26);
		Employee objEmp5 = new Employee(104, "Muthu", 23);
		Employee objEmp6 = new Employee(115, "Monalisa", 25);

		arrEmpList.add(objEmp1);

		arrEmpList.add(objEmp2);
		arrEmpList.add(objEmp3);
		arrEmpList.add(objEmp4);
		arrEmpList.add(objEmp5);
		arrEmpList.add(objEmp6);

		System.out.println("Sorted based on Natural Sorting(Emp Id)");

		System.out.println("Before Sorting");
		dispListContent(arrEmpList);

		System.out.println("Sorting based on Emp Name");
		Collections.sort(arrEmpList, new EmpNameComparator());
		dispListContent(arrEmpList);

		System.out.println("Sorting based on Emp Age");
		Collections.sort(arrEmpList, new EmpAgeComparator());
		dispListContent(arrEmpList);

		System.out.println("Sorting based on EmpId and Name");
		Collections.sort(arrEmpList, new EmpIdNameComparator());
		dispListContent(arrEmpList);
	}

	public static void dispListContent(List<Employee> parrEmployeeLst) {
		System.out.println(" ");

		System.out.println("EmpId" + " " + "EmpName" + "     " + "Age");
		System.out.println("---------------------------");
		for (Employee object : parrEmployeeLst) {
			System.out.print(object.getEmpId() + "   ");
			System.out.print(object.getEmpName() + "     ");
			System.out.println(object.getAge() + " ");
		}
	}
}

EmpNameComparator.java

public class EmpNameComparator implements Comparator<Employee>{

	@Override
	public int compare(Employee o1, Employee o2) {
		String a = o1.getEmpName();
		String b = o2.getEmpName();
		
		//Strings Natural Order Comparable Method
		int compare = a.compareTo(b);
		
		if (compare > 0){
		    return 1;
		}
		else if (compare < 0) {
			return -1;
		}
		else {
			return 0;
		}
	}
}

EmpAgeComparator.java

public class EmpAgeComparator  implements Comparator<Employee> {
	
	@Override
	public int compare(Employee o1, Employee o2) {
		Integer a = o1.getAge();
		Integer b = o2.getAge();
		
		if (a > b){
		    return 1;
		}
		else if (a < b) {
			return -1;
		}
		else {
			return 0;
		}
	}
}

EmpIdNameComparator.java

public class EmpIdNameComparator  implements Comparator<Employee>{
	
	@Override
	public int compare(Employee o1, Employee o2) {
		String a = o1.getEmpName();
		String b = o2.getEmpName();
		
		
		int i = Integer.compare(o1.getEmpId(), o2.getEmpId());
		if (i != 0) return i;

	    return a.compareTo(b);
	}
	
}

Output

Before Sorting
 
EmpId EmpName     Age
---------------------------
101   Ahmed      31 
127   Mahesh     24 
109   Viparna    85 
101   Abdul      26 
104   Muthu      23 
115   Monalisa   25 

Sorting based on Emp Name
 
EmpId EmpName     Age
---------------------------
101   Abdul      26 
101   Ahmed      31 
127   Mahesh     24 
115   Monalisa   25 
104   Muthu      23 
109   Viparna    85 

Sorting based on Emp Age
 
EmpId EmpName     Age
---------------------------
104   Muthu       23 
127   Mahesh      24 
115   Monalisa    25 
101   Abdul       26 
101   Ahmed       31 
109   Viparna     85 

Sorting based on EmpId and Name
 
EmpId EmpName     Age
---------------------------
101   Abdul       26 
101   Ahmed       31 
104   Muthu       23 
109   Viparna     85 
115   Monalisa    25 
127   Mahesh      24 


comparable for natural order, (natural order definition is obviously open to interpretation), and write a comparator for other sorting or comparison needs.

If there is a natural or default way of sorting Object already exist during development of Class than use Comparable. This is intuitive and you given the class name people should be able to guess it correctly like Strings are sorted chronically, Employee can be sorted by there Id etc. On the other hand if an Object can be sorted on multiple ways and client is specifying on which parameter sorting should take place than use Comparator interface. for example Employee can again be sorted on name, salary or department and clients needs an API to do that. Comparator implementation can sort out this problem.

Spring MVC uses 2 design Patterns Internally

  1. Front Controller
  2. MVC

How Spring MVC Handles Request

  1. Receive the request from client
  2. Consult Handle Mapper to decide which controller processes the request
  3. Dispatch the request to the controller
  4. Controller processes the request and returns the logical view name and model back to DispatcherServlet
  5. Consult View Resolver for appropriate View for the logical view name from Controller
  6. Pass the model to View implementation for rendering
  7. View renders the model and returns the result to DispatcherServlet
  8. Return the rendered result from view to the client

MappingHandler
DispatcherServlet uses MappingHandler to find out which controller is right one for this request.There are many MappingHandler implementations which uses different strategies to map the request to Controller. By default DispatcherServlet will use BeanNameUrlHandlerMapping and DefaultAnnotationHandlerMapping.

public interface HandlerMapping 
{
      HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

ViewResolver
With the help of ViewResolver strategy object DispatcherServlet can find out physical view from the logical view name. Similar to MappingHandler there are also many different strategies for resolving the view based on the different view technologies. Most commonly used implementation of ViewResolver is InternalResourceViewResolver.

public interface ViewResolver 
{
      View resolveViewName(String viewName, Locale locale) throws Exception;
}