SpringMVC——MVC、springMVC认识及理解、与Struts2的区别、方法
一、了解MVC
mvc这种设计模式,分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),不光运用于Web领域,而且也能用于非Web领域;可以特指一种表现层设计模式,不限于Java语言;Java Web应用中应用的最广泛的设计模式便是MVC模式,目前的主流Web框架大多也是基于MVC设计模式所编写的。
1、JavaWeb开发模式
C/S:客户端 / 服务器
B/S: 浏览器 / 服务器(主要采用mvc框架模式)
JavaBean:就是一个普通类(实体bean),包含三样标准:无参构造、私有属性、公共的getter和setter方法;
2、mvc在Java web中具体应用
Model:模型可以代表着一种企业规范,就是业务流程/状态的处理以及业务规则的规定,业务模型的设计可以说是MVC的核心。一般Model层包括业务处理层和数据访问层。数据访问层主要是对数据库的一些操作的封装。业务处理层应用JavaBean构建,JavaBean主要是用作将从View层获取的数据和数据库的数据进行桥接。除却JavaBean以外,若想构建分布式应用系统,可以应用EJB组件进行业务逻辑层的构建。
View:视图即是展示给用户实际进行交互的,像HTML、JSP等。
Controller:控制器,一般控制请求的处理逻辑,负责请求转发;具体的可以理解为对View层提交的请求为其设置对应的Servlet进行特定功能的处理,一般是编写在Model中的业务处理层中的,相对于一个中介者的作用。
如图所示:
MVC模式在最熟悉的框架中如:Struts2、spring MVC等等,都是基于MVC模式;
其中总结Model模式,常见的如下:
<1>Jsp+JavaBean
需要在jsp页面中检查请求的参数是否正确,显示和业务逻辑操作会耦合度高,以后维护起来比较困难;相对于纯jsp页面去做开发比较,程序的可读性变高了,大部分代码写在JavaBean上,可重复率变高了(JavaBean的设计就是用来重用、封装,大大减少编写重复代码的工作);
<2>JSP+Servlrt+JavaBean
基于MVC模式的开发进行的,拥有分层思想:高内聚、低耦合;
3、springmvc与spring的关系?
springmvc属于spring框架的后续产品,用在基于MVC的表现层开发,类似于struts2框架;spring参考链接 spring知识点 ;
二、springmvc 的认识
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还可以是 Struts 这样的 Web 框架。
1、springmvc工作流程
(1)客户端通过url发送请求
(2)核心控制器Dispatcher Servlet接收到请求,通过系统或自定义的映射器配置找到对应的handler,并将url映射的控制器controller返回给核心控制器。
(3)通过核心控制器找到系统或默认的适配器
(4)由找到的适配器,调用实现对应接口的处理器,并将结果返回给适配器,结果中包含数据模型和视图对象,再由适配器返回给核心控制器
(5)核心控制器将获取的数据和视图结合的对象传递给视图解析器,获取解析得到的结果,并由视图解析器响应给核心控制器
(6)核心控制器将结果返回给客户端
2、springmvc与struts2的区别(下面以3种区别为例)
<1>springmvc的入口是一个servlet,即前端控制器,例如:*.action
struts2入口是一个filter过虑器,即前端过滤器,例如:/*
<2>springmvc是基于方法开发,传递参数是通过方法形参,可以设计为单例
struts2是基于类开发,传递参数是通过类的属性,只能设计为多例
<3>springmvc通过参数解析器是将request对象内容进行解析成方法形参,将响应数据和页面封装成ModelAndView对象,最后又将模型数据通过request对象传输到页面
struts采用值栈存储请求和响应的数据,通过OGNL存取数据
3、springmvc的理解与方法(下面以核心代码为例子)
3.1 (好理解)快速创建
先创建一个springmvc一个web项目,再导入springioc,springweb , springmvc相关的jar包;
接着在/WEB-INF/下创建web.xml文件
1 <!-- 注册springmvc框架核心控制器 --> 2 <servlet> 3 <servlet-name>xx</servlet-name> 4 <servlet-class>包名.类名</servlet-class> 5 </servlet> 6 <servlet-mapping> 7 <servlet-name>xx</servlet-name> 8 <url-pattern>*.action</url-pattern> 9 </servlet-mapping>
再创建action的控制器类
1 /** 2 * 控制器 3 * 4 */ 5 public class xxAction implements Controller{ 6 /** 7 * 业务方法 8 */ 9 public ModelAndView handleRequest(HttpServletRequest requqest,HttpServletResponse response) throws Exception { 10 ModelAndView modelAndView = new ModelAndView(); 11 modelAndView.addObject("message","第一个springmvc应用程序"); 12 modelAndView.setViewName("/jsp/xx.jsp"); 13 return modelAndView; 14 } 15 }
接下来就是显示JSP文件,在/WebRoot/下创建jsp/xx.jsp
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <html> 4 <head> 5 <title>这是我的第一个springmvc应用程序</title> 6 </head> 7 <body> 8 xx.jsp<br/> 9 ${message} 10 </body> 11 </html>
紧接着在/WEB-INF/创建DispatcherServlet-servlet.xml配置文件,xml头部信息与spring.xml相同;注意:该配置文件的命名规则:web.xml文件中配置的<servlet-name>的值-servlet.xml
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd "> <!-- 控制器(程序员) --> <bean name="/hello.action" class="包名.类名"></bean> <!-- 映射器(框架) --> <bean class="包名.类名"></bean> <!-- 适配器(框架) --> <bean class="包名.类名"></bean> <!-- 视图解析器(框架) --> <bean class="包名.类名"></bean> <!-- 或者直接在这里面引用 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean> </beans>
最后将web项目放到Tomcat中,通过游览器去访问URL;如:http://localost:8080/web
3.2 springmvc.xml配置文件
一般默认情况下,springmvc框架的配置文件必须叫<servlet-name>-servlet.xml , 且必须放在/WEB-INF/目录下;如果想放到自定义目录下,可以在web.xml文件中,为DispatcherServlet配置一个初始化参数,让它去我们指定的目录下加载springmvc.xml配置文件,web.xml代码如下:
1 <!-- 注册springmvc框架核心控制器 --> 2 <servlet> 3 <servlet-name>DispatcherServlet</servlet-name> 4 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 5 <init-param> 6 <param-name>contextConfigLocation</param-name> 7 <param-value>/WEB-INF/classes/包名/springmvc.xml</param-value> 8 </init-param> 9 </servlet> 10 <servlet-mapping> 11 <servlet-name>DispatcherServlet</servlet-name> 12 <url-pattern>*.action</url-pattern> 13 </servlet-mapping>
如果放在SRC目录下,相对于上面的XML代码,需要改动的地方如下:
1 <init-param> 2 <param-name>自己定义的类名</param-name> 3 <param-value>classpath:spring.xml</param-value> 4 </init-param>
3.3 视图解析器
这里浅谈下逻辑名与路径的对应,可以理解为:ModelAndView对象中即可以封装真实视图路径名,也可以封装视图路径的逻辑名;代码如下:
1 <!-- 视图解析器(框架) --> 2 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 3 <property name="xx" value="/jsp/"/> 4 <property name="xx" value=".jsp"/> 5 </bean>
3.4 映射器Mapping
这里面可以思考下,Action接受什么请求?用下面2个代码去理解:
1 <!-- 注册控制器 --> 2 <bean name="/xx.action" class="包名.类名"></bean> 3 4 <!-- 注册映射器(handler包)(框架) --> 5 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
多个JSP交给标签为ID的action;相对于一个Action对应多个路径;
1 <!-- 注册控制器 --> 2 <bean id="userActionID" class="包名.类名"></bean> 3 4 <!-- 注册映射器 --> 5 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 6 <property name="mappings"> 7 <props> 8 <prop key="/x1.action">userActionID</prop> 9 <prop key="/x2.action">userActionID</prop> 10 <prop key="/x3.action">userActionID</prop> 11 </props> 12 </property> 13 </bean>
3.5 适配器
主要Action实现了什么?理解如下:
1 //实现Controller接口 2 public class XX implements Controller{ 3 public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception { 4 System.out.println("xx::handleRequest"); 5 request.setCharacterEncoding("UTF-8"); 6 String username = request.getParameter("username"); 7 ModelAndView modelAndView = new ModelAndView(); 8 modelAndView.addObject("message",username); 9 modelAndView.setViewName("/jsp/xxx.jsp"); 10 return modelAndView; 11 } 12 }
3.6 控制器——可以不经过定义的控制
1 <!--以下面2个例子去理解 --> 2 <!-- /index.action请求,直接转发到/index.jsp页面 --> 3 <bean name="/index.action" class="org.springframework.web.servlet.mvc.ParameterizableViewController"> 4 <property name="viewName" value="/index.jsp"/> 5 </bean> 6 7 <!--扩展理解 --> 8 <!-- 注册视图解析器( 9 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 10 <property name="prefix" value="/"/> 11 <property name="suffix" value=".jsp"/> 12 </bean> 13 -->
还有一种引用,能够以实体的形式,收集客户端的参数
1 public class xx extends AbstractCommandController{ 2 public xx(){ 3 this.setCommandClass(Admin.class); 4 } 5 @Override 6 protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response, Object obj, BindException bindException)throws Exception { 7 System.out.println("xx::handle"); 8 ModelAndView modelAndView = new ModelAndView(); 9 Admin admin = null; 10 if(obj instanceof Admin){ 11 admin = (Admin) obj; 12 } 13 modelAndView.addObject("username",admin.getUsername()); 14 modelAndView.addObject("gender",admin.getGender()); 15 modelAndView.addObject("hiredate",admin.getHiredate()); 16 modelAndView.setViewName("/jsp/xx.jsp"); 17 return modelAndView; 18 } 19 } 20 21 <!-- 请求处理类 --> 22 <bean name="/add.action" class="包类.类名"> 23 </bean> 24 25 <!-- 映射器 --> 26 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> 27 </bean>
3.7 日期转换器、编码过滤器
在默认情况下,springmvc不能将String类型转成Date类型,必须自定义类型转换器
1 public class xx extends AbstractCommandController{ 2 @Override 3 protected void xx(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception { 4 binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); 5 }
专用于解决POST提交中文乱码问题,需要在web.xml文件中配置;
1 <!-- 编码过滤器 --> 2 <filter> 3 <filter-name>文件名</filter-name> 4 <filter-class> 5 org.springframework.web.filter.CharacterEncodingFilter 6 </filter-class> 7 <init-param> 8 <param-name>encoding</param-name> 9 <param-value>UTF-8</param-value> 10 </init-param> 11 </filter> 12 <filter-mapping> 13 <filter-name>文件名</filter-name> 14 <url-pattern>/*</url-pattern> 15 </filter-mapping>
3.8 与Struts2的区别
个人初步理解主要有3点:
1、入口:springmvc的入口是一个servlet;例如:*.action;struts2入口是一个filter过滤器,例如:/*
2、开发:springmvc是基于方法开发,传递参数是通过方法形参,可以设计为单例;struts2是基于类开发,传递参数是通过类的属性,只能设计为多例;
3、数据:springmvc通过参数解析器是将request对象内容进行解析成方法形参,将响应数据和页面封装成ModelAndView对象,最后又将模型数据通过request对象传输到页面; struts采用值栈存储请求和响应的数据,通过OGNL存取数据;
三、方法(可能应用到的)
1、在业务控制方法中写入普通变量收集参数
可以在业务控制方法中,以参数形式收集客户端参数,springmvc采用方法参数形式的
1 @Controller 2 @RequestMapping(value="/user") 3 public class xx{ 4 @RequestMapping(value="/add") 5 public String add(Model model,int id,String name,Double sal) throws Exception{ 6 System.out.println("HelloAction::add()"); 7 System.out.println(id + ":" + name + ":" + sal); 8 model.addAttribute("message","增加用户"); 9 return "/xx.jsp"; 10 } 11 }
2、限定某个业务控制方法,只允许GET或POST请求方式访问
1 @Controller 2 @RequestMapping(value="/user") 3 public class UserAction{ 4 @RequestMapping(value="/add",method=RequestMethod.POST) 5 public String add(Model model,int id,String name,double sal) throws Exception{ 6 System.out.println("HelloAction::add()::POST"); 7 System.out.println(id + ":" + name + ":" + sal); 8 model.addAttribute("message","增加用户"); 9 return "/success.jsp"; 10 } 11 }
3、在业务中写入Request,Response等传统web参数
1 @Controller 2 @RequestMapping(value="/user") 3 public class UserAction{ 4 @RequestMapping(value="/add",method=RequestMethod.POST) 5 public void add(HttpServletRequest request,HttpServletResponse response) throws Exception{ 6 System.out.println("HelloAction::add()::POST"); 7 int id = Integer.parseInt(request.getParameter("id")); 8 String name = request.getParameter("name"); 9 double sal = Double.parseDouble(request.getParameter("sal")); 10 System.out.println(id + ":" + name + ":" + sal); 11 request.getSession().setAttribute("id",id); 12 request.getSession().setAttribute("name",name); 13 request.getSession().setAttribute("sal",sal); 14 response.sendRedirect(request.getContextPath()+"/register.jsp"); 15 } 16 }
4、异步发送表单数据到JavaBean,并响应JSON文本返回(核心部分)
1 <form> 2 编号:<input type="text" name="id" value="1"/><br/> 3 姓名:<input type="text" name="name" value="哈哈"/><br/> 4 薪水:<input type="text" name="sal" value="5000"/><br/> 5 <input type="button" value="异步提交注册"/> 6 </form> 7 8 <script type="text/javascript"> 9 $(":button").click(function(){ 10 var url = "${pageContext.request.contextPath}/add.action"; 11 var sendData = { 12 "id":1, 13 "name":"哈哈", 14 "sal":5000 15 }; 16 $.post(url,sendData,function(backData,textStatus,ajax){ 17 alert(ajax.responseText); 18 }); 19 }); 20 </script>
相应的Spring.xml文件
1 <!-- Action控制器 --> 2 <context:component-scan base-package="包名.类名"/> 3 4 5 <!-- 配适器 --> 6 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 7 <property name="xx"> 8 <list> 9 <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> 10 </list> 11 </property> 12 </bean>
end...