Simple Integrated Development of MVC & Security in Spring 3 (I)

Spring MVC module is a concise Web application framework, which implements MVC mode to handle HTTP requests and responses. Compared with Struts series, Spring MVC's MVC is more obvious. It completely separates the definition of controller and view, and they do not need to be in a namespace. It has all the advantages of Spring, and bean s are more comfortable to configure. Spring 3's annotation configuration makes coding more elegant. This example combines Spring MVC and Security framework for small integration, only functional description, do not explore its principles in detail.  
First, build a project to do a simple message publishing function. The code structure is as follows. Maven can manage dependencies very well.
 
Hierarchical structure is adopted, but no database operations are used. A brief description is given. Database operations are used to authenticate users in the later Security framework. Let's look at dependencies, so that we can get a clearer understanding of Spring's hierarchy:

First, look at the basic web deployment description file web.xml. Write down the configuration used. Spring 3 uses Dispatcher Servlet to send requests, while the Security framework concatenates the filter mechanism for security processing. Configuration is simple, as follows, web requests in the form of. htm:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  6.     <context-param>  
  7.         <param-value>  
  8.         /WEB-INF/board-service.xml  
  9.         /WEB-INF/board-security.xml  
  10.         </param-value>  
  11.     </context-param>  
  12.     <listener>  
  13.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  14.     </listener>  
  15.     <filter>  
  16.         <filter-name>springSecurityFilterChain</filter-name>  
  17.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  18.     </filter>  
  19.     <filter-mapping>  
  20.         <filter-name>springSecurityFilterChain</filter-name>  
  21.         <url-pattern>/*</url-pattern>  
  22.     </filter-mapping>  
  23.     <servlet>  
  24.         <servlet-name>board</servlet-name>  
  25.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  26.     </servlet>  
  27.     <servlet-mapping>  
  28.         <servlet-name>board</servlet-name>  
  29.         <url-pattern>*.htm</url-pattern>  
  30.     </servlet-mapping>  
  31. </web-app>  

The following is the configuration file of the Servlet, because we use annotations. Here, we only need to explain the view file, but also cooperate with the Security Framework. Here, we also declare the method interception annotations of the Security Framework. Here, we show that to intercept the Controller's method, we must use the Securit to intercept the Controller's method. The declaration of Y and Servlet are placed in a file, otherwise interception will not work:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:security="http://www.springframework.org/schema/security"  
  5.     xmlns:context="http://www.springframework.org/schema/context"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  8. http://www.springframework.org/schema/context  
  9. http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  10. http://www.springframework.org/schema/security  
  11. http://www.springframework.org/schema/security/spring-security-3.0.xsd">  
  12.     <context:component-scan base-package="org.ourpioneer.board.web" />  
  13.     <bean  
  14.     class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
  15.         <property name="prefix" value="/WEB-INF/jsp/" />  
  16.         <property name="suffix" value=".jsp" />  
  17.     </bean>  
  18.     <security:global-method-security  
  19.         jsr250-annotations="enabled" secured-annotations="enabled" />  
  20. </beans>  

The component scan of the org.ourpioneer.board.web package will reveal the controller of our annotation declaration. The following is the explanation of view parsing. We write the view file under / WEB-INF/jsp / and the file with the suffix of. jsp is the view file. Why declare the prefix and suffix well? Because we can write the file name directly in the program, it is very flexible, it does not care whether it is the same as the request path. The following is the configuration of the Security framework intercepted by the Controller method.  
Configuration of Servlet related content, the rest is Service content, this is very simple, declare a bean is, in order to cooperate with the Security framework to connect to the database to verify user identity, here also configure a data source, using Spring's own data source implementation:
  1. <bean id="dataSource"        class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  2. <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
  3.     <property name="url"  
  4.         value="jdbc:mysql://localhost:3306/board" />  
  5.     <property name="username" value="root" />  
  6.     <property name="password" value="123" />  
  7. </bean>  
  8. <bean id="messageBoardService" class="org.ourpioneer.board.service.MessageBoardServiceImpl" />  

After configuring, let's take a look at the program code. First, let's look at the domain object Message defined, a very simple bean:
  1. package org.ourpioneer.board.domain;  
  2. public class Message {  
  3.     private Long id;  
  4.     private String author;  
  5.     private String title;  
  6.     private String body;  
  7. //The getter and setter methods are omitted  
  8. }  

The following is Service. We use the principle of separation of implementation and interface, and we may not use it in Web Service, but it is a good design principle. Four method declarations are defined in the interface:
  1. package org.ourpioneer.board.service;  
  2. import java.util.List;  
  3. import org.ourpioneer.board.domain.Message;  
  4. public interface MessageBoardService {  
  5.     public List<Message> listMessages();  
  6.     public void postMessage(Message message);  
  7.     public void deleteMeesage(Message message);  
  8.     public Message findMessageById(Long messageId);  
  9. }  

The following is the implementation class of Service, just use List to place Message. Here we also intercept the method of Service safely. This is a more fine-grained interception. It will be described in detail later. Now we can ignore:
  1. package org.ourpioneer.board.service;  
  2. import java.util.ArrayList;  
  3. import java.util.LinkedHashMap;  
  4. import java.util.List;  
  5. import java.util.Map;  
  6. import org.ourpioneer.board.domain.Message;  
  7. import org.springframework.security.access.annotation.Secured;  
  8. public class MessageBoardServiceImpl implements MessageBoardService {  
  9.     private Map<Long, Message> messages = new LinkedHashMap<Long, Message>();  
  10.     //@Secured( { "ROLE_ADMIN", "IP_LOCAL_HOST" })  
  11.     public synchronized void deleteMeesage(Message message) {  
  12.         messages.remove(message.getId());  
  13.     }  
  14.     //@Secured( { "ROLE_USER", "ROLE_GUEST" })  
  15.     public Message findMessageById(Long messageId) {  
  16.         return messages.get(messageId);  
  17.     }  
  18.     //@Secured( { "ROLE_USER", "ROLE_GUEST" })  
  19.     public List<Message> listMessages() {  
  20.         return new ArrayList<Message>(messages.values());  
  21.     }  
  22.     //@Secured( { "ROLE_USER" })  
  23.     public synchronized void postMessage(Message message) {  
  24.         message.setId(System.currentTimeMillis());  
  25.         messages.put(message.getId(), message);  
  26.     }  
  27. }  

Next it's time to get into the controller section. Let's look at it one by one.
  1. package org.ourpioneer.board.web;  
  2. import java.util.List;  
  3. import org.ourpioneer.board.domain.Message;  
  4. import org.ourpioneer.board.service.MessageBoardService;  
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.security.access.annotation.Secured;  
  7. import org.springframework.stereotype.Controller;  
  8. import org.springframework.ui.Model;  
  9. import org.springframework.web.bind.annotation.RequestMapping;  
  10. import org.springframework.web.bind.annotation.RequestMethod;  
  11. @Controller  
  12. @RequestMapping("/messageList.htm")  
  13. public class MessageListController {  
  14.     @Autowired  
  15.     private MessageBoardService messageBoardService;  
  16.     @RequestMapping(method = RequestMethod.GET)  
  17.     //@Secured( { "ROLE_USER" })  
  18.     public String generateList(Model model) {  
  19.         List<Message> messages = java.util.Collections.emptyList();  
  20.         messages = messageBoardService.listMessages();  
  21.         model.addAttribute("messages", messages);  
  22.         return "messageList";  
  23.     }  
  24. }  

The annotated declaration of this kind of controller is the controller in Spring MVC. The following is the request mapping declaration, which handles the request of / messageList.htm. The injection of Service is automatically assembled, even the set method is not used. The following is the processing method. It can be seen that this is a simple POJO, even the method name is. We customize, just declare the HTTP request method, you can find the method, and Model is the object to pass data to the page, put the list of messages obtained into it, to see the return value, a string, what does it mean? JSP page name, is it simple, MVC performance incisive and vivid, this will find the page.  
The following are the classes for publishing messages:
  1. package org.ourpioneer.board.web;  
  2. import javax.servlet.http.HttpServletRequest;  
  3. import org.ourpioneer.board.domain.Message;  
  4. import org.ourpioneer.board.service.MessageBoardService;  
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.security.access.annotation.Secured;  
  7. import org.springframework.stereotype.Controller;  
  8. import org.springframework.ui.Model;  
  9. import org.springframework.validation.BindingResult;  
  10. import org.springframework.web.bind.annotation.ModelAttribute;  
  11. import org.springframework.web.bind.annotation.RequestMapping;  
  12. import org.springframework.web.bind.annotation.RequestMethod;  
  13. @Controller  
  14. @RequestMapping("/messagePost.htm")  
  15. public class MessagePostController {  
  16.     @Autowired  
  17.     private MessageBoardService messageBoardService;  
  18.     @RequestMapping(method = RequestMethod.GET)  
  19.     //@Secured( { "ROLE_USER" })  
  20.     public String setupForm(Model model) {  
  21.         Message message = new Message();  
  22.         model.addAttribute("message", message);  
  23.         return "messagePost";  
  24.     }  
  25.     @RequestMapping(method = RequestMethod.POST)  
  26.     //@Secured( { "ROLE_USER" })  
  27.     public String onSubmit(@ModelAttribute("message") Message message,  
  28.             BindingResult result, HttpServletRequest request) {  
  29.         message.setAuthor(request.getRemoteUser());  
  30.         if (result.hasErrors()) {  
  31.             return "messagePost";  
  32.         } else {  
  33.             messageBoardService.postMessage(message);  
  34.             return "redirect:messageList.htm";  
  35.         }  
  36.     }  
  37. }  

GET is to request to this page, POST is to publish a message, and finally redirect to messageList.htm, which is such a simple configuration. Note that the method implementation, first look at the page request method setupForm (model model model), the parameters have been explained above, is the data object passed to the page, which placed a Message object, what is the use? Sure page used, but this is an empty object, then naturally think of binding to form attributes, and then look at the page will be clear. The following is the onSubmit method, in which the parameters are defined by myself. Just remember that BindingResult should be written with the data object parameter Message, and the latter parameters can be written as you want. Then I want to use the HttpServletRequest object, and write it. It's really flexible. The implementation of the method is very simple, let alone talk about it.  
Finally, the function is deleted, which is simpler:
  1. package org.ourpioneer.board.web;  
  2. import org.ourpioneer.board.domain.Message;  
  3. import org.ourpioneer.board.service.MessageBoardService;  
  4. import org.springframework.beans.factory.annotation.Autowired;  
  5. import org.springframework.security.access.annotation.Secured;  
  6. import org.springframework.stereotype.Controller;  
  7. import org.springframework.ui.Model;  
  8. import org.springframework.web.bind.annotation.RequestMapping;  
  9. import org.springframework.web.bind.annotation.RequestMethod;  
  10. import org.springframework.web.bind.annotation.RequestParam;  
  11. @Controller  
  12. @RequestMapping("/messageDelete.htm")  
  13. public class MessageDeleteController {  
  14.     @Autowired  
  15.     private MessageBoardService messageBoardService;  
  16.     @RequestMapping(method = RequestMethod.GET)  
  17.     //@Secured( { "ROLE_ADMIN" })  
  18.     public String messageDelete(  
  19.             @RequestParam(required = true, value = "messageId") Long messageId,  
  20.             Model model) {  
  21.         Message message = messageBoardService.findMessageById(messageId);  
  22.         messageBoardService.deleteMeesage(message);  
  23.         model.addAttribute("messages", messageBoardService.listMessages());  
  24.         return "redirect:messageList.htm";  
  25.     }  
  26. }  

Only if the permissions are set to administrator permissions can they be deleted, which is not necessary here. To look at the method parameters, we need a request parameter, messageId, to delete the identifier of the message. Here's the operation. It's very simple.  
Finally, take a look at the page:
  1. <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>  
  2. <%@taglib prefix="security"  
  3.     uri="http://www.springframework.org/security/tags"%>  
  4. <html>  
  5. <head>  
  6. <title>Message List</title>  
  7. </head>  
  8. <body>  
  9. <h2>Welcome! <security:authentication property="name" /></h2>  
  10. <security:authentication property="authorities" var="authorities" />  
  11. <ul>  
  12.     <c:forEach items="${authorities}" var="authority">  
  13.         <li>${authority.authority}</li>  
  14.     </c:forEach>  
  15. </ul>  
  16. <hr />  
  17. <c:forEach items="${messages}" var="message">  
  18.     <table>  
  19.         <security:authorize ifAllGranted="ROLE_ADMIN,ROLE_USER">  
  20.             <tr>  
  21.                 <td>Author</td>  
  22.                 <td>${message.author}</td>  
  23.             </tr>  
  24.         </security:authorize>  
  25.         <tr>  
  26.             <td>Title</td>  
  27.             <td>${message.title}</td>  
  28.         </tr>  
  29.         <tr>  
  30.             <td>Body</td>  
  31.             <td>${message.body}</td>  
  32.         </tr>  
  33.         <tr>  
  34.             <td colspan="2"><a  
  35.                 href="messageDelete.htm?messageId=${message.id}">Delete</a></td>  
  36.         </tr>  
  37.     </table>  
  38.     <hr />  
  39. </c:forEach>  
  40. <a href="messagePost.htm">Post</a>  
  41. <a href="<c:url value="/j_spring_security_logout" />">Logout</a>  
  42. </body>  
  43. </html>  

List pages have the use of Security framework tags, which can be annotated first when doing MVC only. JSTL tags are used here to traverse the message list, which is very simple.  
Following is the page for publishing messages:
  1. <%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>  
  2. <html>  
  3. <head>  
  4. <title>Message Post</title>  
  5. </head>  
  6. <body>  
  7. <form:form method="POST" modelAttribute="message">  
  8.     <table>  
  9.         <tr>  
  10.             <td>Title</td>  
  11.             <td><form:input path="title" /></td>  
  12.         </tr>  
  13.         <tr>  
  14.             <td>Body</td>  
  15.             <td><form:textarea path="body" /></td>  
  16.         </tr>  
  17.         <tr>  
  18.             <td colspan="2"><input type="submit" value="Post" /></td>  
  19.         </tr>  
  20.     </table>  
  21. </form:form>  
  22. </body>  
  23. </html>  

The data binding mentioned above is easy to see here. There is nothing more to explain.  
When you're ready, you're ready to run. Let's start Jetty and see how it works. For Jetty's configuration, please refer to the author's previous comments on Integration of Maven and Jetty The description is very detailed.  
 
Because I combined the Security framework, I saw the list of identities I logged in. Here's the message, which is very simple:
 

Keywords: Spring Java xml JSP

Added by wmolina on Mon, 08 Jul 2019 07:02:10 +0300