一、SpringMVC 简介
SpringMVC 是 Spring 针对 MVC 设计模式所推出的一种框架,尤其是针对 MVC 模式中的控制层。SpringMVC 结构设计完全符合传统的 MVC 设计开发。最大特点在于简单易用。
MVC 设计模式
在当今的企业级项目开发中,MVC 设计模式是主要的设计模式,是行业所遵循的。Java EE 最初的设计阶段,MVC 的结构如下:
实际上可将以上结构分为两部分
Web 开发技术:JSP + Servlet + Filter + JSTL + EL + JavaScript + jQuery + ......(Web 开发技术通俗来讲就是前端技术,相对复杂许多,因为其需要与用户交互,也即显示层和控制层)
EJB 开发技术:会话 Bean(SessionBean)、实体 Bean(EntityBean)、消息驱动 Bean(MessageDriverBean),包含业务层和数据层会话 Bean:进行业务处理实体 Bean:数据层,进行数据库操作消息驱动 Bean:Java 消息服务(JMS),产生出了 ActiveMQ、RabbitMQ、Kafka
图 MVC 设计模式
资金雄厚的企业往往选择付费软件,例如 web 容器选择 IBM 的 WebSphere,数据库选择 Oracle 或者 DB2,银行系统就是用了 WebSphere 容器。
web 开发技术与会话层互相访问,需要通过远程协议 RMI(Remote Method Invocation)进行。同时,远程访问,传递参数,故 VO 类需要序列化。这也是 VO 对象序列化的原因。
图 Web 与 EJB 远程访问
因为 EJB 技术过于复杂,同时思想超前。所以,人们将精力更多的放到了 web 技术上。并且,由于免费容器的推出和一系列框架的诞生,诸如 struts、spring、hibernate 等。使得开发越来越便捷。而 SpringMVC 可以说是控制层框架里目前发展最好的,很好的解决了一下 MVC 设计问题:
更多的多业务处理,避免开发者进行反射操作;
轻松实现 VO 与传递参数的互相转换,本质在于 servlet,可以通过 request 对象获取客户端请求的所有信息,再通过反射机制最终实现转换;
提供了拦截器(struts1.x 没有拦截器,struts2.x 才有拦截器),为服务器端接受的参数进行验证;
便捷的文件上传;
提供安全的访问机制,所有 JSP 保存在 WEB-INF 后可以轻松取得。
二、配置 Spring MVC 开发环境
2.1、在配置 Spring 框架的基础上,增加 SpringMVC 包的支持,pom.xml 配置文件添加的信息如下:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.13.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.13.RELEASE</version> </dependency>
复制代码
2.2、web.xml 增加 Spring 框架支持
2.2.1、SpringMVC 是建立在 Spring 容器之上运行的,因此,项目需要添加 Spring 框架支持。Spring 容器的启动交由 web 容器控制,在 web.xml 文件中添加监听。
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
复制代码
2.2.2、Spring 容器启动,需要 applicationContext.xml 配置文件的支持,这样才能读取 Spring 容器的上下文信息,因此,需要添加 applicationContext.xml 的位置信息。
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/classes/applicationContext.xml </param-value> </context-param>
复制代码
2.2.3、Spring 容器之中添加 SpringMVC 需要的处理用户请求的操作类(org.springframework.web.servlet.DispatcherServlet),由这个操作类进行参数的验证、后续程序的调用以及用户请求的处理。
<servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
复制代码
2.2.4、Spring 提供了过滤器进行编码过滤
<filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
复制代码
2.2.5、添加 applicationContext-mvc.xml 配置文件,专门负责 MVC 的配置,同时添加 Spring MVC 框架的规则支持,以下展示简要部分。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"></beans>
复制代码
2.2.6、配置文件打开注解支持以及 applicationContext-mvc.xml 增加 mvc 的注解支持和默认 servlet 操作类
<context:annotation-config/> <context:component-scan base-package="org.fuys.own"/> <mvc:annotation-driven/> <mvc:default-servlet-handler/>
复制代码
三、SpringMVC 程序示例
處理數據發送至 JSP 頁面進行顯示,由控制層跳轉到 JSP 頁面進行參數傳遞需要使用 request 屬性範圍,這個 request 屬性對象可以通過 ModelAndView 進行控制。
org.springframework.web.servlet.ModelAndView 沒有父類,實際上負責頁面跳轉和參數傳遞,類似與 request.getRequestDispatcher()、forward()、request.setAttribute()。
Java 源程序:
package org.fuys.own.controller;import java.util.ArrayList;import java.util.Map;import java.util.UUID;import java.util.WeakHashMap;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;@Controller@RequestMapping("/goal/*")public class GoalController { private Logger logger = LoggerFactory.getLogger(GoalController.class); // 1、從類到方法上的整體請求路徑的簡易設置 @RequestMapping("/goal") // 2、開發者自定義返回數據類型,若爲空,則頁面顯示http狀態為404 // 3、可以直接定義傳遞參數 public void goal(String goalId){ logger.info("Goal id is " + goalId); } // ModelAndView負責頁面跳轉和參數傳遞 @RequestMapping("queryGoalList") public ModelAndView queryQoalList(String name){ logger.info("Goals' name is " + name); return null; } @RequestMapping("updateGoal") public ModelAndView updateGoal(String goalId){ ModelAndView mav = new ModelAndView("/pages/goal.jsp"); mav.addObject("goal", goalId); logger.info("GoalId is " + goalId); return mav; } @RequestMapping("addGoal") public ModelAndView addGoal(String name){ Map<String, Object> map = new WeakHashMap<>(); map.put("goalId", UUID.randomUUID()); map.put("name", name); ModelAndView mav = new ModelAndView("/pages/goal.jsp"); mav.addAllObjects(map); mav.addObject("goal", "okay"); logger.info("GoalId is " + map); return mav; }}
复制代码
四、SpringMVC 方法參數
4.1、使用 int 進行接收
@RequestMapping("/test") public ModelAndView test(int id){ logger.info("test id is " + id); return null; }
复制代码
4.2、設置參數名稱
儅出現傳遞參數名稱和方法參數名稱不一致時,可以通過設置參數名稱,達到正確傳參。
@RequestMapping("/test") public ModelAndView test(@RequestParam("tid") int id){ logger.info("test id is " + id); return null; }
复制代码
4.3、分頁處理
若沒有傳遞參數值,則可以設置默認值。
@RequestMapping("querytestList") public ModelAndView queryTestList( @RequestParam(value="cp",defaultValue="1")int currentPage, @RequestParam(value="ls",defaultValue="10")int lineSize, @RequestParam(value="kw",defaultValue="test")String keyword){ logger.info("currentPage is " + currentPage); logger.info("lineSize is " + lineSize); logger.info("keyword is " + keyword); return null; }
复制代码
4.4、内置對象設置
使用 HttpServletRequest 和 HttpServletResponse 類進行處理操作。例如:cookie、頭信息、映射路徑以及 Ajax 輸出支持。
@RequestMapping("getTest") public ModelAndView getTest(@RequestParam(value="tid",defaultValue="10")int id, HttpServletRequest request,HttpServletResponse response){ logger.info(" *** id ***" + id); logger.info(" *** sessionId ***" + request.getSession().getId()); logger.info(" *** contextPath ***" + request.getContextPath()); logger.info(" *** realPath ***" + request.getServletContext().getRealPath("/")); try { response.getWriter().print("request and response object"); } catch (IOException e) { e.printStackTrace(); } return null; }
复制代码
4.5、參數與 VO 轉換
VO 類:
package org.fuys.own.vo;import java.io.Serializable;import org.springframework.stereotype.Repository;@Repositorypublic class Goal implements Serializable { private static final long serialVersionUID = -3571483870932700806L; private String goalId; private String name; private String description;}
复制代码
controller 類方法:
@RequestMapping("/goal") public void goal(Goal goal){ logger.info("Goal id is " + goal.getGoalId()); }
复制代码
爲了能夠處理傳遞參數包含日期的問題,則定義一個父類,進行日期的格式化處理,建議該父類為抽象類,可以方便擴展。该方式便是一个模板设计模式的应用。
package org.fuys.own.controller;import java.text.SimpleDateFormat;import java.util.Date;import org.springframework.beans.propertyeditors.CustomDateEditor;import org.springframework.web.bind.WebDataBinder;import org.springframework.web.bind.annotation.InitBinder;/** * define public abstract class for controller * to get public method * @author ys * */public abstract class AbstractController { /** * format date parameter * @param data */ @InitBinder public void initBinder(WebDataBinder data) { data.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), true)); }}
复制代码
對於對象嵌套的問題,傳遞參數可以使用“對象.屬性”進行參數傳遞。
五、安全訪問
在整個 web 項目的目錄中,WEB-INF 是具有最高的安全級別,標準的 Spring 結構應當把 JSP 頁面放置于 WEB-INF 目錄下。傳統的方式文件保存在 WEB-INF 目錄下,就必須通過配置文件 web.xml 取得。所以,Spring 對此,進行了改進,既保存在 WEB-INF 目錄下,又能夠方便取得。
下面在 applicationContext-mvc.xml 文件裏追加配置。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean>
复制代码
六、配置資源文件
現在開發的項目都會使用到屬性文件,因此,也可以通過配置的方式對資源文件進行操作處理,資源文件如 log4j.properties 文件。下面在 applicationContext-mvc.xml 文件裏添加配置。其中 id 的名稱固定。
配置文件:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <array> <value>log4j</value> </array> </property> </bean>
复制代码
Java 代碼:
package org.fuys.own.controller;import javax.annotation.Resource;import org.springframework.context.MessageSource;/** * define public abstract class for controller * to get public method * @author ys */public abstract class AbstractController { @Resource private MessageSource messageSource; public String getValue(String key,Object ...args){ return this.messageSource.getMessage(key, args, Locale.getDefault()); }}
复制代码
评论