Outline:
1) Annotation Based Url Mapping Config
2) Pass Value from View to Controller
3) Pass Value from Controller to View
HandlerMapping
1) SimpleUrlHandlerMapping (Not often used)
<beans ...> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <value> /index.htm=welcomeController /welcome.htm=welcomeController /main.htm=welcomeController /home.htm=welcomeController </value> </property> </bean> <bean id="welcomeController" class="com.mkyong.common.controller.WelcomeController" /> </beans>
2) ControllerBeanNameHandlerMapping (Not often userd)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/context/spring-mvc.xsd"> <!-- Handler Mapping --> <bean class="org.springframework.web.servlet.mvc.support.ControllerBeanNameHandlerMapping" /> <bean name="/welcome.html" class="edu.xmu.webproject.controller.WelcomeController"></bean> </beans>
3) DefaultAnnotationHandlerMapping (Often used)
springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="edu.xmu.webproject.controller" /> <mvc:annotation-driven /> <!-- View Resolver for JSPs --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
HelloController.java
package edu.xmu.webproject.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { // RequestMapping represents which url mapped to this method @RequestMapping({ "/hello", "/" }) public String hello() { return "hello"; } }
hello.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <h1>Hello</h1> </body> </html>
Final Test
2. Value Transportation
1) Pass Value from View to Controller
HelloController.java
package edu.xmu.webproject.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class HelloController { // RequestMapping represents which url mapped to this method @RequestMapping({ "/hello", "/" }) public String hello(@RequestParam("username") String userName) { System.out.println("username=" + userName); return "hello"; } }
Request Url
http://localhost:8080/WebProject/hello?username=davy
Console Output
username=davy
Request Url
http://localhost:8080/WebProject/hello
Got HTTP Stauts 400 Error. Bad request.
Why? Cause spring-mvc supports RESTFUL style, as long as we pass the params, RESTFUL style regards that as a part of URL.
2) A more simple way to pass value from View to Controller
HelloController.java
package edu.xmu.webproject.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { // RequestMapping represents which url mapped to this method @RequestMapping({ "/hello", "/" }) public String hello(String username) { System.out.println("username=" + username); return "hello"; } }
We removed the annotation "@RequestParam". That requires "username" be exactly the same with the request url's param key.
http://localhost:8080/WebProject/hello?username=davy # username=davy http://localhost:8080/WebProject/hello # username=null http://localhost:8080/WebProject/hello?userName=davy # username=null
3) Pass value from Controller to View
HelloController.java
package edu.xmu.webproject.controller; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { // RequestMapping represents which url mapped to this method @RequestMapping({ "/hello", "/" }) public String hello(String username, Map<String, Object> context) { System.out.println("username=" + username); context.put("username", username); return "hello"; } }
hello.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <h1>Hello ${username}</h1> </body> </html>
Request Url
http://localhost:8080/WebProject/hello?username=davy
Output
Hello davy
4) A recommanded way to pass value from Controller to View
HelloController.java
package edu.xmu.webproject.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { // RequestMapping represents which url mapped to this method @RequestMapping({ "/hello", "/" }) public String hello(String username, Model model) { System.out.println("username=" + username); model.addAttribute("username", username); // The key is the type of the value, first letter lowercase model.addAttribute(username); return "hello"; } }
hello.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <h1>Hello ${username} & ${string}</h1> </body> </html>
3. Model Driven Value Transportation
What if we need to pass 20 params to the controller?
How should we encapsulate these params into Object/Model?
Example below shows how to use model driven to pass model between view and controller.
1) User.java
package edu.xmu.webproject.bean; public class User { private String username; private String password; private String nickname; private String email; public User(String username, String password, String nickname, String email) { super(); this.username = username; this.password = password; this.nickname = nickname; this.email = email; } public User() { super(); } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
2) UserController.java
package edu.xmu.webproject.controller; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import edu.xmu.webproject.bean.User; @Controller @RequestMapping("/user") public class UserController { private Map<String, User> userMap = new HashMap<String, User>(); public UserController() { userMap.put("davy", new User("Davy", "Jones", "davy", "[email protected]")); userMap.put("calypso", new User("Calypso", "Jones", "carl", "[email protected]")); userMap.put("obama", new User("Obama", "Barack", "obama", "[email protected]")); userMap.put("tom", new User("Tom", "Cruize", "tom", "[email protected]")); } @RequestMapping(value = "/users", method = RequestMethod.GET) public String listAllUsers(Model model) { System.out.println("List all users"); model.addAttribute("userMap", userMap); return "/user/list"; } // This method nevigate us to the page for add user @RequestMapping(value = "/add", method = RequestMethod.GET) public String addUser(Model model) { System.out.println("Nevigate to add user page"); // For the benefit of open model driven model.addAttribute("user", new User()); return "/user/add"; } // This method handle the request for add user @RequestMapping(value = "/add", method = RequestMethod.POST) public String addUser(User user) { System.out.println("Add user"); String username = user.getUsername(); userMap.put(username, user); return "redirect:/user/users"; } }
3) list.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <a href="add">Add User</a> <br /> <c:forEach items="${userMap}" var="user"> ---------${user.value.username} ---------${user.value.password} ---------${user.value.nickname} ---------${user.value.email} <br /> </c:forEach> </body> </html>
4) add.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <!-- Here we didn't assign an action for this form. --> <!-- By default, the form will be submitted to current path '/user/add' --> <!-- With the method POST --> <sf:form method="post" modelAttribute="user"> username: <sf:input path="username" /> <sf:errors path="username"/> <br /> password: <sf:input path="password" /><sf:errors path="password"/> <br /> nickname: <sf:input path="nickname" /> <br /> email: <sf:input path="email" /><sf:errors path="email"/> <br /> <input type="submit" value="Submit" /> </sf:form> </body> </html>
5) springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="edu.xmu.webproject.controller" /> <mvc:annotation-driven /> <!-- View Resolver for JSPs --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property> <property name="prefix" value="/WEB-INF/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
6) web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>WebProject</display-name> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
7) pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>edu.xmu.web.WebProject</groupId> <artifactId>WebProject-Core</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <spring.version>3.0.5.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- Spring 3 dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- JSTL --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> <configuration> <webXml>WebContent\WEB-INF\web.xml</webXml> </configuration> </plugin> </plugins> </build> </project>
8) Final Test
Model Driven Summary:
1) Model from Controller to View to display user info:
1> Store beans to model
@RequestMapping(value = "/users", method = RequestMethod.GET) public String listAllUsers(Model model) { System.out.println("List all users"); model.addAttribute("userMap", userMap); return "/user/list"; }
2> Use JSTL in JSP page in order to display model content
<!-- JSTL --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> ... <c:forEach items="${userMap}" var="user"> ---------${user.value.username} ---------${user.value.password} ---------${user.value.nickname} ---------${user.value.email} <br /> </c:forEach>
2) Model from View to Controller to add user info:
1> Open model driven in controller, if we don't add User to model, then the view will not know the type of Model.
Exceptions below will occur:
十一月 09, 2013 8:29:48 下午 org.springframework.web.servlet.tags.RequestContextAwareTag doStartTag 严重: Neither BindingResult nor plain target object for bean name 'user' available as request attribute java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute
// First way to open model driven // This method nevigate us to the page for add user @RequestMapping(value = "/add", method = RequestMethod.GET) public String addUser(Model model) { System.out.println("Nevigate to add user page"); // For the benefit of open model driven model.addAttribute("user", new User()); return "/user/add"; } // Second way to open model driven // This method nevigate us to the page for add user @RequestMapping(value = "/add", method = RequestMethod.GET) public String addUser(@ModelAttribute("user") User user) { System.out.println("Nevigate to add user page"); return "/user/add"; }
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%> ... <sf:form method="post" modelAttribute="user"> username: <sf:input path="username" /> <sf:errors path="username"/> <br /> password: <sf:input path="password" /><sf:errors path="password"/> <br /> nickname: <sf:input path="nickname" /> <br /> email: <sf:input path="email" /><sf:errors path="email"/> <br /> <input type="submit" value="Submit" /> </sf:form>
// This method handle the request for add user @RequestMapping(value = "/add", method = RequestMethod.POST) public String addUser(User user) { System.out.println("Add user"); String username = user.getUsername(); userMap.put(username, user); return "redirect:/user/users"; }
Reference Links:
1) http://www.mkyong.com/spring-mvc/configure-the-handler-mapping-priority-in-spring-mvc/
2) http://docs.spring.io/spring/docs/3.0.x/reference/mvc.html