框架-springmvc(ssm整合)
第一天
课程安排:
1、什么是springMVC?
2、springMVC框架原理前端控制器、处理器映射器、处理器适配器、视图解析器。
3、springMVC入门程序目的:对前端控制器、处理器映射器、处理器适配器、视图解析器非注解的处理器映射器、处理器适配器注解的处理器映射器、处理器适配器
4、springMVC和mybatis整合
5、springMVC注解开发常用的注解学习参数绑定(简单类型、pojo、集合类型)自定义参数绑定
6、springMVC和struts2的区别
1、springMVC框架
1.1、什么是springMVC
springMVC是spring框架的一个模块,springMVC和spring无需通过中间整合层进行整合。
springMVC是一个基于MVC的web框架。
1.2、什么是MVC
MVC是一个设计模式,MVC在b/s系统下的应用:
1.3、springMVC框架
第一步:发起请求到 前端控制器DispatcherServlet
。
第二步:前端控制器请求处理器映射器HandlerMapping
查找Handler。
可以根据xml配置、注解进行查找。
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
。
第四步:前端控制器调用处理器适配器去执行Handler。
第五步:处理器适配器HandlerAdapter
去执行Handler。
第六步:Handler执行完成给适配器返回ModelAndView
。
第七步:处理器适配器向前端控制器返回ModelAndView。
ModelAndView是springMVC框架的一个底层对象,包括model和view。
第八步:前端控制请求视图解析器
去进行视图解析。
根据逻辑视图名解析成真正的视图(jsp)。
第九步:视图解析器向前端控制器返回view。
第十步:前端控制器进行视图渲染。
视图渲染将模型数据(在ModelAndView对象中)填充到request域。
第十一步:前端控制器向用户响应结果。
组件:
1、前端控制器DispatcherServlet(不需要程序员开发)
作用:接收请求,响应结果,相当于转发器、中央处理器。
2、处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的url查找Handler
3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
4、处理器Handler(需要程序员开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。
5、视图解析器View resolver(不需要程序员开发)
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
6、视图view(需要程序员开发jsp)
view是一个接口,实现类支持不用的view类型(jsp、freemarker、pdf……)
2、入门程序
2.1、环境准备
数据库环境:
/* Navicat MySQL Data TransferSource Server : ZWD Source Server Version : 50711 Source Host : localhost:3306 Source Database : mybatisTarget Server Type : MYSQL Target Server Version : 50711 File Encoding : 65001Date: 2019-11-29 17:34:25 */SET FOREIGN_KEY_CHECKS=0;-- ---------------------------- -- Table structure for `items` -- ---------------------------- DROP TABLE IF EXISTS `items`; CREATE TABLE `items` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) NOT NULL COMMENT '商品名称',`price` float(10,1) NOT NULL COMMENT '商品定价',`detail` text COMMENT '商品描述',`pic` varchar(64) DEFAULT NULL COMMENT '商品图片',`createtime` datetime NOT NULL COMMENT '生产日期',PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of items -- ---------------------------- INSERT INTO `items` VALUES ('1', '台式机', '3000.0', '该电脑质量非常好!!!!', null, '2015-02-03 13:22:53'); INSERT INTO `items` VALUES ('2', '笔记本', '6000.0', '笔记本性能好,质量好!!!!!', null, '2015-02-09 13:22:57'); INSERT INTO `items` VALUES ('3', '背包', '200.0', '名牌背包,容量大质量好!!!!', null, '2015-02-06 13:23:02');-- ---------------------------- -- Table structure for `orderdetail` -- ---------------------------- DROP TABLE IF EXISTS `orderdetail`; CREATE TABLE `orderdetail` (`id` int(11) NOT NULL AUTO_INCREMENT,`orders_id` int(11) NOT NULL COMMENT '订单id',`items_id` int(11) NOT NULL COMMENT '商品id',`items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',PRIMARY KEY (`id`),KEY `FK_orderdetail_1` (`orders_id`),KEY `FK_orderdetail_2` (`items_id`),CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of orderdetail -- ---------------------------- INSERT INTO `orderdetail` VALUES ('1', '1', '2', '3'); INSERT INTO `orderdetail` VALUES ('2', '2', '3', '5'); INSERT INTO `orderdetail` VALUES ('3', '2', '2', '3');-- ---------------------------- -- Table structure for `orders` -- ---------------------------- DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL COMMENT '下单用户id',`number` varchar(32) NOT NULL COMMENT '订单号',`createtime` datetime NOT NULL COMMENT '创建订单时间',`note` varchar(100) DEFAULT NULL COMMENT '备注',PRIMARY KEY (`id`),KEY `FK_orders_1` (`user_id`),CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of orders -- ---------------------------- INSERT INTO `orders` VALUES ('1', '10', '11', '2019-09-18 09:41:28', '33'); INSERT INTO `orders` VALUES ('2', '1', '10', '2019-11-20 16:48:52', '44');-- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(32) NOT NULL COMMENT '用户名称',`birthday` date DEFAULT NULL COMMENT '生日',`sex` char(1) DEFAULT NULL COMMENT '性别',`address` varchar(256) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', '张晓敏', null, '2', null); INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市'); INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州'); INSERT INTO `user` VALUES ('25', '赵文迪', '2019-09-10', '女', '贵州遵义'); INSERT INTO `user` VALUES ('27', '赵文迪', '2019-09-09', '女', '贵州遵义'); INSERT INTO `user` VALUES ('28', '赵文迪', '2019-09-09', '女', '贵州遵义'); INSERT INTO `user` VALUES ('29', '赵文迪', '2019-09-09', '女', '贵州遵义');
创建web项目:jdk1.8+tomcat8.0
导入spring的jar包:需要spring4.3所有jar(一定包括spring-webmvc-4.3.0.RELEASE.jar)
2.2、配置前端控制器
在类路径下添加文件:springmvc.xml
在web.xml文件中配置前端控制器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"><display-name>01.springmvc入门程序</display-name><!-- 配置springMVC前端控制器 --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--contextConfigLocation:配置springMVC加载的配置文件如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><!-- 第一种:*.action:访问一.action结尾由DispatcherServlet进行解析第二种:/:所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析。使用此种方式可以实现RESTFUL风格的url.第三种:/*:这样配置不对,使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错 --><url-pattern>*.action</url-pattern></servlet-mapping><!-- 配置springMVC前端控制器 --><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list>
</web-app>
2.3、配置处理其适配器
在类路径下的springmvc.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 配置处理器适配器:所有的处理器适配器都实现HandlerAdapter接口--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置处理器映射器 -->
<!-- 视图解析器 --></beans>
SimpleControllerHandlerAdapter:
支持实现Controller
的Handler。
2.5、编写Handler
编写一个实现Controller
接口的Handler。ItemsController1.java
package com.zwd.ssm.controller;import java.util.ArrayList;
import java.util.List;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;import com.zwd.ssm.po.Items;
/*** 实现Controller接口的处理器* @author Administrator**/
public class ItemsController1 implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println("进来。");//调用serviceList<Items> itemsList = new ArrayList<>();Items item1 = new Items();item1.setId(1);item1.setName("aaa");item1.setPrice(777);Items item2 = new Items();item1.setId(2);item1.setName("BBB");item1.setPrice(888);itemsList.add(item1);itemsList.add(item2);//返回ModelAndViewModelAndView modelAndView = new ModelAndView();//相当于request的setAttribute,在jsp页面中通过itemsList获取数据modelAndView.addObject("itemsList", itemsList);//指定视图modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");return modelAndView;}
}
2.6 、编写前端页面jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!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=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/item/queryItem.action" method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询"/></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr><td>商品名称</td><td>商品价格</td><td>生产日期</td><td>商品描述</td><td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr><td>${item.name }</td><td>${item.price }</td><td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td><td>${item.detail }</td><td><a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td></tr>
</c:forEach></table>
</form>
</body></html>
2.7、配置处理器映射器
在类路径下的springmvc.xml
中配置:
<!-- 2、配置处理器映射器 --><!-- BeanNameUrlHandlerMapping:将bean的name作为url进行查找,需要配置Handler时指定beanName(就是url) --><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean><!-- 配置Handler --><bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1"></bean>
2.8、配置视图解析器
在springmvc.xml
中配置视图解析器。
<!-- 3、视图解析器 --><!-- InternalResourceViewResolver:解析jsp,默认使用jstl标签。注意导入jstl的包 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
整个springmvc.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 1、配置处理器适配器:所有的处理器适配器都实现HandlerAdapter接口--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 2、配置处理器映射器 --><!-- BeanNameUrlHandlerMapping:将bean的name作为url进行查找,需要配置Handler时指定beanName(就是url) --><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean><!-- 配置Handler --><bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1"></bean><!-- 3、视图解析器 --><!-- InternalResourceViewResolver:解析jsp,默认使用jstl标签。注意导入jstl的包 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean></beans>
2.9、访问页面
http://localhost:8080/01.springmvcFirst/queryItems.action
3、非注解的处理器映射器和适配器
3.1、非注解的处理器映射器
类型1:BeanNameUrlHandlerMapping
<!-- 类型1:BeanNameUrlHandlerMapping:将bean的name作为url进行查找,需要配置Handler时指定beanName(就是url) --><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> </bean><!-- 配置Handler --><bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1"> </bean>
类型2: SimpleUrlHandlerMapping
<!-- 类型2:SimpleUrlHandlerMapping --><bean id="itemsController" class="com.zwd.ssm.controller.ItemsController1"></bean><bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"><property name="mappings"><props><prop key="/queryItems1.action">itemsController</prop><prop key="/queryItems2.action">itemsController</prop></props></property></bean>
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 1、配置处理器适配器:所有的处理器适配器都实现HandlerAdapter接口--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 2、配置处理器映射器:两种类型可以并存 --><!-- 类型1:BeanNameUrlHandlerMapping:将bean的name作为url进行查找,需要配置Handler时指定beanName(就是url) --><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean><!-- 配置Handler --><bean id="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1"></bean><!-- 类型2:SimpleUrlHandlerMapping --><bean id="itemsController" class="com.zwd.ssm.controller.ItemsController1"></bean><bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"><property name="mappings"><props><prop key="/queryItems1.action">itemsController</prop><prop key="/queryItems2.action">itemsController</prop></props></property></bean><!-- 3、视图解析器 --><!-- InternalResourceViewResolver:解析jsp,默认使用jstl标签。注意导入jstl的包 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean></beans>
前端映射器会找到对应url使用的处理器映射器,能使用哪个就使用哪个。
3.2、非注解的适配器
类型1:SimpleControllerHandlerAdapter
<!-- 类型1:要求:需要编写的Handler实现Controller接口 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
package com.zwd.ssm.controller;import java.util.ArrayList;
import java.util.List;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;import com.zwd.ssm.po.Items;
/*** 实现Controller接口的处理器* @author Administrator**/
public class ItemsController1 implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {//调用serviceList<Items> itemsList = new ArrayList<>();Items item1 = new Items();item1.setId(1);item1.setName("aaa");item1.setPrice(777);Items item2 = new Items();item1.setId(2);item1.setName("BBB");item1.setPrice(888);Items item3 = new Items();item1.setId(3);item1.setName("ccc");item1.setPrice(999);itemsList.add(item1);itemsList.add(item2);itemsList.add(item3);//返回ModelAndViewModelAndView modelAndView = new ModelAndView();//相当于request的setAttribute,在jsp页面中通过itemsList获取数据modelAndView.addObject("itemsList", itemsList);//指定视图modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");return modelAndView;}
}
类型2:HttpRequestHandlerAdapter
<!-- 类型2:要求:需要编写的Handler实现HttpRequestHandler接口 -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
</bean>
package com.zwd.ssm.controller;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.HttpRequestHandler;import com.zwd.ssm.po.Items;
/*** 实现HttpRequestHandler的接口* @author Administrator**/
public class ItemsController2 implements HttpRequestHandler {@Overridepublic void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//调用serviceList<Items> itemsList = new ArrayList<>();Items item1 = new Items();item1.setId(1);item1.setName("aaa");item1.setPrice(777);Items item2 = new Items();item1.setId(2);item1.setName("BBB");item1.setPrice(888);Items item3 = new Items();item1.setId(3);item1.setName("ccc");item1.setPrice(999);itemsList.add(item1);itemsList.add(item2);itemsList.add(item3);//设置模型数据request.setAttribute("itemsList", itemsList);//设置转发视图request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);//使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据
// response.setCharacterEncoding("utf-8");
// response.setContentType("application/json;charset=utf-8");
// response.getWriter().write("json串");}
}
3.3、DispatcherServlet.properties
前端控制器从上边的文件中加载处理器映射器、适配器、视图解析器等组件,如果不在springmvc.xml
中配置,则使用默认加载的。
4、注解的处理器映射器和适配器
4.1、注解处理器映射器
3.1之前使用:
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
3.1之后使用:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
4.2、注解适配器
3.1之前使用:
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
3.1之后使用:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
4.3、配置注解映射器和适配器
记得添加mvc约束。
<!-- 注解的适配器和映射器的配置 --><!-- 方式一:单独配置两个 --><!-- 1、配置注解的处理器适配器: --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean><!-- 2、配置注解的处理器映射器: --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean><!-- 方式二:使用mvc:annotation-driven代理方式一。 mvc:annotation-driven:默认加载很多的参数绑定方法。比如json转换解析器就默认加载了。实际开发使用mvc:annotation-driven--><mvc:annotation-driven></mvc:annotation-driven>
<?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:mvc="http://www.springframework.org/schema/mvc"xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 注解的适配器和映射器的配置 --><!-- 方式一:单独配置两个 --><!-- 1、配置注解的处理器适配器: --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean><!-- 2、配置注解的处理器映射器: --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean><!-- 方式二:使用mvc:annotation-driven代理方式一。 mvc:annotation-driven:默认加载很多的参数绑定方法。比如json转换解析器就默认加载了。实际开发使用mvc:annotation-driven--><mvc:annotation-driven></mvc:annotation-driven><!--视图解析器 --><!-- InternalResourceViewResolver:解析jsp,默认使用jstl标签。注意导入jstl的包 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean></beans>
4.4、注解Handler编写
@Controller、@RequestMapping
@Controller:使用@Controller注解标识该类是一个控制器。
@RequestMapping:使用@RequestMapping实现handleRequest方法和url的映射,一个方法对应一个url
注解适配器和注解映射器需要配套使用。
ItemsController3.java
package com.zwd.ssm.controller;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.RequestMapping;import com.zwd.ssm.po.Items;
/*** 使用注解的映射器、适配器的Controller* @author Administrator**/
//处理器适配器:使用@Controller注解标识该类是一个控制器
@Controller
public class ItemsController3{//处理器映射器注解:使用@RequestMapping实现handleRequest方法和url的映射,一个方法对应一个url//一般建议url和方法名称一致。@RequestMapping("/queryItems")public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//调用serviceList<Items> itemsList = new ArrayList<>();Items item1 = new Items();item1.setId(1);item1.setName("aaa");item1.setPrice(777);Items item2 = new Items();item1.setId(2);item1.setName("BBB");item1.setPrice(888);Items item3 = new Items();item1.setId(3);item1.setName("ccc");item1.setPrice(999);itemsList.add(item1);itemsList.add(item2);itemsList.add(item3);//设置模型数据request.setAttribute("itemsList", itemsList);//设置转发视图request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);//使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据
// response.setCharacterEncoding("utf-8");
// response.setContentType("application/json;charset=utf-8");
// response.getWriter().write("json串");}//其它方法
}
4.5、将Handler注入aop
<!-- 配置Controller --><!-- <bean class="com.zwd.ssm.controller.ItemsController3"></bean> 或者直接扫描注解 -->
<!-- 扫描注解: -->
<context:component-scan base-package="com.zwd.ssm.controller"></context:component-scan>
4.6、访问调试
http://localhost:8080/03.HandlerMappingAndAdapter_anno/queryItems.action
5、源码分析
分析springmvc的执行过程。
第一步:前端控制器接受请求
调用doDispatch()
第二步:前端控制器调用处理器映射器。根据url查找handler
第三步:根据handler查找对应的处理器适配器,并调用该适配器执行该handler返回ModelAndView
第四步:视图渲染。将model数据填充到request域。
视图解析得到view。
6、入门程序小结
前端控制器
<!-- 配置springMVC前端控制器 --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!--contextConfigLocation:配置springMVC加载的配置文件如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><!-- 第一种:*.action:访问一.action结尾由DispatcherServlet进行解析第二种:/:所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析。使用此种方式可以实现RESTFUL风格的url.第三种:/*:这样配置不对,使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错 --><url-pattern>*.action</url-pattern></servlet-mapping>
处理器映射器
非注解的处理器映射器(两种):BeanNameUrlHandlerMapping
、SimpleUrlHandlerMapping
<!-- 类型1:BeanNameUrlHandlerMapping:将bean的name作为url进行查找,需要配置Handler时指定beanName(就是url) --><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> </bean><!-- 配置Handler --><bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1"> </bean><!-- 类型2:SimpleUrlHandlerMapping --><bean id="itemsController" class="com.zwd.ssm.controller.ItemsController1"></bean><bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"><property name="mappings"><props><prop key="/queryItems1.action">itemsController</prop><prop key="/queryItems2.action">itemsController</prop></props></property></bean>
处理器适配器
非注解的处理器适配器(两种):SimpleControllerHandlerAdapter
、HttpRequestHandlerAdapter
<!-- 类型1:要求:需要编写的Handler实现Controller接口 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 类型2:要求:需要编写的Handler实现HttpRequestHandler接口 -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
</bean>
注解的处理器映射器和适配器
<!-- 注解的适配器和映射器的配置 --><!-- 方式一:单独配置两个 --><!-- 1、配置注解的处理器适配器: --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean><!-- 2、配置注解的处理器映射器: --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean><!-- 方式二:使用mvc:annotation-driven代理方式一。 mvc:annotation-driven:默认加载很多的参数绑定方法。比如json转换解析器就默认加载了。实际开发使用mvc:annotation-driven--><mvc:annotation-driven></mvc:annotation-driven>
视图解析器
<!--视图解析器 --><!-- InternalResourceViewResolver:解析jsp,默认使用jstl标签。注意导入jstl的包 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/items"></property><!-- 前缀 --><property name="suffix" value=".jsp"></property><!-- 后缀 --></bean>
//在视图解析器中配置前缀和后缀//<property name="prefix" value="/WEB-INF/jsp/"></property><!-- 前缀 -->//<property name="suffix" value=".jsp"></property><!-- 后缀 -->request.getRequestDispatcher("items/itemsList").forward(request, response);
7、springMVC和mybatis整合
7.1、需求
使用springMVC和mybatis完成商品列表的查询。
7.2、整合思路
springmvc和mybatis的系统架构
第一步:整合dao层
mybatis和spring整合,通过spring管理mapper接口。
使用mapper的扫描器自动扫描mapper接口在spring中的注册。MapperScannerConfigurer
第二步:整合service层
通过spring管理service接口。
通过配置方式将service接口配置在spring配置文件中。
实现事务控制(xml配置)。
第三步:整合springmvc的模块,不需要整合。
7.3、准备环境
创建web项目
导包:数据库连接驱动+数据库连接池+mybatis的jar包+mybatis和spring整合jar包+日志包+spring的jar包+jstl。
在类路径下创建日志文件:
log4j.properties
# Global logging configuration # 在开发环境下使用DEBUG;在生产环境下使用info或者error log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
在类路径下创建数据库配置文件:
db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=root
7.4、整合dao
sqlMapConfig.xml
创建
sqlMapConfig.xml
文件:config->mybatis->sqlMapConfig.xml<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 1、配置全局settings:根据需要配置 --><!-- 2、配置别名 --><typeAliases><!-- 批量扫描别名 --><package name="com.zwd.ssm.po"/><!-- 单个别名定义 <typeAlias type="" alias=""/>--></typeAliases><!--3、配置mapper:由于使用spring和mybatis的整合包进行mapper扫描,这里就不需要配置了(MapperScannerConfigurer)。必须遵循:mapper.xml和mapper.java文件同名且在一个目录 --><!-- <mappers></mappers> --></configuration>
applicationContext_dao.xml
mapper批量扫描器:MapperScannerConfigurer
创建
applicationContext.xml
文件:config->mybatis->applicationContext.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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 1、配置数据库的连接 --> <!-- 加载数据库配置文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 通过数据库连接池dpcp连接和管理数据库 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="${jdbc.driver}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="maxActive" value="30"></property><property name="maxIdle" value="5"></property></bean> <!-- 2、配置mybatis的SqlSessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 数据源 --><property name="dataSource" ref="dataSource"></property><!-- 配置mybatis的全局配置文件sqlMapConfig.xml --><property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml"></property></bean> <!-- 3、配置扫描mapper生成dao的实现类:在此处配置就不用在sqlMapConfig.xml文件中配置mapper扫描 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 扫描包下的mapper,如果需要扫描多个包使用逗号分隔开 --><property name="basePackage" value="com.zwd.ssm.mapper"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean></beans>
逆向工程生成po类和mapper
手动定义商品查询mapper
针对综合查询mapper,一般情况会有相关关联查询,建议自定义mapper。
定义Items.java
的扩展类:ItemsCusotm.java
package com.zwd.ssm.po;
/*** 商品类的扩展类* @author Administrator**/
public class ItemsCustom extends Items {//扩展属性
}
定义Items.java
的包装类(包装了查询条件):ItemsVo.java
package com.zwd.ssm.po;
/*** 商品包装对象* @author Administrator**/
public class ItemsVo {//包装查询条件private ItemsCustom items ;public ItemsCustom getItemsCustom() {return items;}public void setItemsCustom(ItemsCustom items) {this.items = items;}
}
ItemsMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.zwd.ssm.mapper.ItemsMapper" ><sql id="itemsList_where"><if test="items != null"><if test="items.name != null and items.name != ''">name like '%${items.name}%'</if></if></sql><!-- 查询商品信息:parameterType:传入包装对象(包装了查询条件) resultType:建议使用扩展对象--><select id="findItemsList" parameterType="com.zwd.ssm.po.ItemsVo" resultType="com.zwd.ssm.po.ItemsCustom">select * from items <where><include refid="itemsList_where"></include></where></select></mapper>
ItemsMapper.java
package com.zwd.ssm.mapper;import java.util.List;import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.po.ItemsVo;public interface ItemsMapper {/*** 查询商品信息* @param itemsVo* @return*/public List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception;
}
7.5、整合service
ItemsService接口和实现类
ItemsService.java
package com.zwd.ssm.service;import java.util.List;import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.po.ItemsVo;/*** 商品信息的service层接口* @author Administrator**/
public interface ItemsService {/*** 查询商品信息* @param itemsVo* @return* @throws Exception */public List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception;
}
ItemsServiceImpl.java
package com.zwd.ssm.service.impl;import java.util.List;import javax.annotation.Resource;import org.springframework.stereotype.Service;import com.zwd.ssm.mapper.ItemsMapper;
import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.po.ItemsVo;
import com.zwd.ssm.service.ItemsService;
/*** 商品信息service层实现类* @author Administrator**/
//@Service
public class ItemsServiceImpl implements ItemsService {@Resource(name="itemsMapper")private ItemsMapper itemsMapper;@Overridepublic List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception {return itemsMapper.findItemsList(itemsVo);}
}
使用xml配置管理service
applicationContext_service.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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 配置service --> <bean id="itemsService" class="com.zwd.ssm.service.impl.ItemsServiceImpl"></bean>
</beans>
使用xml配置管理事务
applicationContext_tx.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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 配置事务控制 --><!-- 1、配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 2、配置事务的通知 --><tx:advice id="tx_Advice" transaction-manager="transactionManager"><tx:attributes><tx:method name="insert*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="find*" propagation="SUPPORTS" read-only="true"/></tx:attributes></tx:advice><!-- 3、配置aop --> <aop:config><aop:pointcut expression="execution(* com.zwd.ssm.servie.impl.*.*(..))" id="cut1"/><aop:advisor advice-ref="tx_Advice" pointcut-ref="cut1"/></aop:config>
</beans>
7.6、整合MVC
配置前端控制器web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"><display-name>04.ssm</display-name><!-- 配置springMVC前端控制器 --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!--contextConfigLocation:配置springMVC加载的配置文件如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><!-- 第一种:*.action:访问一.action结尾由DispatcherServlet进行解析第二种:/:所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析。使用此种方式可以实现RESTFUL风格的url.第三种:/*:这样配置不对,使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错 --><url-pattern>*.action</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list>
</web-app>
配置springmvc.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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 1、扫描注解 --><context:component-scan base-package="com.zwd.ssm.controller"></context:component-scan><!-- 2、配置注解的处理器适配器和映射器 --><mvc:annotation-driven></mvc:annotation-driven><!-- 3、配置视图解析器 --><!-- InternalResourceViewResolver:解析jsp,默认使用jstl标签。注意导入jstl的包 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/items"></property><!-- 前缀 --><property name="suffix" value=".jsp"></property><!-- 后缀 --></bean>
</beans>
jsp页面itemsList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!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=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/queryItem.action" method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询"/></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr><td>商品名称</td><td>商品价格</td><td>生产日期</td><td>商品描述</td><td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr><td>${item.name }</td><td>${item.price }</td><td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td><td>${item.detail }</td><td><a href="${pageContext.request.contextPath }/editItem.action?id=${item.id}">修改</a></td></tr>
</c:forEach></table>
</form>
</body></html>
编写Controller
package com.zwd.ssm.controller;import java.util.List;import javax.annotation.Resource;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.service.ItemsService;/*** 商品信息Controller层* * @author Administrator**/
@Controller
public class ItemsController {@Resource(name = "itemsService")private ItemsService itemsService;@RequestMapping("/queryItems")public ModelAndView queryItems() throws Exception {System.out.println("成功!");// 调用serviceList<ItemsCustom> itemsList = itemsService.findItemsList(null);// 返回ModelAndViewModelAndView modelAndView = new ModelAndView();// 相当于request的setAttribute,在jsp页面中通过itemsList获取数据modelAndView.addObject("itemsList", itemsList);// 指定视图modelAndView.setViewName("/itemsList");return modelAndView;}
}
配置spring容器的监听器web.xml
<!-- 加载spring容器 --><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/classes/spring/applicationContext_*.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"><display-name>04.ssm</display-name><!-- 加载spring容器 --><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/classes/spring/applicationContext_*.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 配置springMVC前端控制器 --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!--contextConfigLocation:配置springMVC加载的配置文件如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><!-- 第一种:*.action:访问一.action结尾由DispatcherServlet进行解析第二种:/:所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析。使用此种方式可以实现RESTFUL风格的url.第三种:/*:这样配置不对,使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错 --><url-pattern>*.action</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list>
</web-app>
7.7、部署访问
http://localhost:8080/04.ssm/queryItems.action
8、修改商品信息功能开发
使用上一个例子(7)的环境
8.1、需求
操作流程:
1、进入商品查询列表页面(jsp/items/itemsList.jsp
)
2、点击修改,进入商品修改页面(jsp/items/editItems.jsp
),页面中显示了要修改的商品(从数据库中查询)
要修改的商品从数据库中查询,根据商品id(主键)查询商品信息。
3、在商品修改页面,修改商品信息,修改后,点击提交。页面跳转到jsp/success.jsp
8.2、mapper开发
mapper:使用逆向工程中的方法。
1、根据id查询商品信息。selectByPrimaryKey()
2、根据id更新items表的数据。updateByPrimaryKeyWithBLOBs()
8.3、service开发
service:
1、根据id查询商品信息
2、修改商品信息
ItemsService.java
package com.zwd.ssm.service;import java.util.List;import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.po.ItemsVo;/*** 商品信息的service层接口* @author Administrator**/
public interface ItemsService {/*** 查询商品信息* @param itemsVo* @return* @throws Exception */public List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception;/*** 根据id查询商品信息* @param id* @return*/public ItemsCustom findItemsById(Integer id);/*** 根据id更新商品信息* @param itemsId* @param items*/public void updateItemsById(Integer itemsId,ItemsCustom itemsCustom);
}
ItemsServiceImpl.java
package com.zwd.ssm.service.impl;import java.util.List;import javax.annotation.Resource;import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.zwd.ssm.mapper.ItemsMapper;
import com.zwd.ssm.mapper.ItemsMapperExample;
import com.zwd.ssm.po.Items;
import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.po.ItemsVo;
import com.zwd.ssm.service.ItemsService;
/*** 商品信息service层实现类* @author Administrator**/
@Service("itemsService")
public class ItemsServiceImpl implements ItemsService {@Resource(name="itemsMapper")private ItemsMapper itemsMapper;@Autowiredprivate ItemsMapperExample ItemsMapperExample;/*** 查询商品信息*/@Overridepublic List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception {return itemsMapper.findItemsList(itemsVo);}/*** 查询商品信息*/@Overridepublic ItemsCustom findItemsById(Integer id) {Items items = ItemsMapperExample.selectByPrimaryKey(id);//中间对商品进行业务处理//...//将所有信息封装到items的扩展类ItemsCustom中ItemsCustom itemsCustom = new ItemsCustom();//将items的属性值拷贝到itemsCustom中BeanUtils.copyProperties(items, itemsCustom);return itemsCustom;}/*** 查询商品信息*/@Overridepublic void updateItemsById(Integer itemsId, ItemsCustom itemsCustom) {//添加业务校验,通常在service中对关键参数进行校验//校验id是否为空,如果为空抛出异常。itemsCustom.setId(itemsId);ItemsMapperExample.updateByPrimaryKeyWithBLOBs(itemsCustom);}
}
8.4、controller开发
方法:
1、商品信息修改页面显示。
2、商品信息修改提交。
商品信息页面和提交成功后的页面
editItems.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!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=UTF-8">
<title>修改商品信息</title></head>
<body> <form id="itemForm" action="${pageContext.request.contextPath }/editItemsSubmit.action" method="post" >
<input type="hidden" name="id" value="${itemsCustom.id }"/>
修改商品信息:
<table width="100%" border=1>
<tr><td>商品名称</td><td><input type="text" name="name" value="${itemsCustom.name }"/></td>
</tr>
<tr><td>商品价格</td><td><input type="text" name="price" value="${itemsCustom.price }"/></td>
</tr>
<tr><td>商品生产日期</td><td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
</tr>
<%-- <tr><td>商品图片</td><td><c:if test="${item.pic !=null}"><img src="/pic/${item.pic}" width=100 height=100/><br/></c:if><input type="file" name="pictureFile"/> </td>
</tr> --%>
<tr><td>商品简介</td><td><textarea rows="3" cols="30" name="detail">${itemsCustom.detail }</textarea></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/>
</td>
</tr>
</table></form>
</body></html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"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=UTF-8">
<title>成功提示</title>
</head>
<body>
哈哈
</body>
</html>
ItemsController
没有实现页面之间的数据传送。
package com.zwd.ssm.controller;import java.util.List;import javax.annotation.Resource;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.service.ItemsService;/*** 商品信息Controller层* * @author Administrator**/
@Controller
public class ItemsController {@Resource(name = "itemsService")private ItemsService itemsService;@RequestMapping("/queryItems")public ModelAndView queryItems() throws Exception {System.out.println("成功!");// 调用serviceList<ItemsCustom> itemsList = itemsService.findItemsList(null);// 返回ModelAndViewModelAndView modelAndView = new ModelAndView();// 相当于request的setAttribute,在jsp页面中通过itemsList获取数据modelAndView.addObject("itemsList", itemsList);// 指定视图modelAndView.setViewName("items/itemsList");return modelAndView;}/*** 修改商品信息页面展示* @return* @throws Exception*/@RequestMapping("/editItems")public ModelAndView editItems() throws Exception{ItemsCustom itemsCustom = itemsService.findItemsById(1);//返回ModelAndViewModelAndView modelAndView = new ModelAndView();modelAndView.addObject("itemsCustom", itemsCustom);modelAndView.setViewName("items/editItems");return modelAndView;}/*** 修改提交商品信息* @return* @throws Exception*/@RequestMapping("/editItemsSubmit")public ModelAndView editItemsSubmit() throws Exception{//获取提交的items,更新到数据库//返回ModelAndViewModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("success");return modelAndView;}}
8.6、部署访问
http://localhost:8080/05.updateItemsInfo/queryItems.action
9、@RequestMapping
使用上一个例子(8)的环境
url映射
定义controller方法对应的url,进行处理器映射使用。
窄化请求映射
限制http请求方式
10、Controller方法返回值
返回ModelAndView
需要在方法结束时定义ModelAndView,将model和view分别进行设置。
/*** 修改商品信息页面展示* @return* @throws Exception*/@RequestMapping("/editItems")public ModelAndView editItems() throws Exception{ItemsCustom itemsCustom = itemsService.findItemsById(1);//返回ModelAndViewModelAndView modelAndView = new ModelAndView();modelAndView.addObject("itemsCustom", itemsCustom);modelAndView.setViewName("items/editItems");return modelAndView;}
返回string
表示返回逻辑视图名:真正视图(jsp路径)=前缀+逻辑视图名+后缀。
/*** 修改商品信息页面展示:返回值string* @return* @throws Exception*/@RequestMapping("/editItems")public String editItems(Model model) throws Exception{ItemsCustom itemsCustom = itemsService.findItemsById(1);//Model:通过形参中的model将model数据传到页面//相当于modelAndView.addObject("itemsCustom", itemsCustom)方法model.addAttribute("itemsCustom", itemsCustom);return "items/editItems";}
redirect重定向
商品修改提交后,重定向到商品查询列表。
redirect重定向特点:浏览器地址栏中的url会变化。
修改提交的request数据无法传到重定向的地址。因为重定向后重新发送一个请求,
request无法共享。
//重定向 return "redirect:queryItems.action";
forword页面转发
通过forward进行页面转发,浏览器地址栏url不变,request可以共享。
//请求转发 return "forward:queryItems.action";
返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
1、使用request转向页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);
2、也可以通过response页面重定向:
response.sendRedirect("url")
3、也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().write("json串");
11、参数绑定
11.1、参数绑定过程
客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。
springMVC中,接收页面提交的数据时通过方法形参来接收的。而不是在controller类中定义成员变量接收。
11.2、默认支持的类型
直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。
HttpServletRequest
通过request对象获取请求信息。
HttpServletResponse
通过response处理响应信息。
HttpSession
通过session对象得到session中存放的对象。
Model/ModelMap
model是一个接口,modelMap是一个接口实现。
作用:将model数据填充到request域。
11.3、简单类型
@RequestParam
通过@RequestParam对简单类型的参数进行绑定。
如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致。
//参数绑定:@RequestParam里面将request传入的参数名称和形参进行绑定。//value:标签的name属性值//required:该参数是否必须传入//defaultValue:默认值public ModelAndView editItems(@RequestParam(value="id",required=true,defaultValue="1") int id)
/*** 修改商品信息页面展示* @return* @throws Exception*/@RequestMapping("/editItems")//参数绑定:@RequestParam里面将request传入的参数名称和形参进行绑定。//value:标签的name属性值//required:该参数是否必须传入//defaultValue:默认值public ModelAndView editItems(@RequestParam(value="id",required=true,defaultValue="1") int id) throws Exception{ItemsCustom itemsCustom = itemsService.findItemsById(id);//返回ModelAndViewModelAndView modelAndView = new ModelAndView();modelAndView.addObject("itemsCustom", itemsCustom);modelAndView.setViewName("items/editItems");return modelAndView;}
11.4、pojo绑定
要求:页面中input的name值和controller形参中的pojo的属性名称一致即可完成绑定。
/*** 修改提交商品信息:pojo参数绑定* @return* @throws Exception*/@RequestMapping("/editItemsSubmit")public String editItemsSubmit(Integer id,ItemsCustom itemsCustom) throws Exception{//获取提交的items,更新到数据库itemsService.updateItemsById(id, itemsCustom);//重定向//return "redirect:queryItems.action";//请求转发return "forward:queryItems.action";}
页面input的name值:
形参ItemsCustom中的属性名称:
11.5、自定义参数类型绑定实现日期类型绑定
对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。
自定义日期类型转换
需要实现Converter
类中的convert()
方法。
package com.zwd.ssm.controller.converter;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;import org.springframework.core.convert.converter.Converter;public class DateConverter implements Converter<String, Date> {//实现将日期串转为Date日期类型@Overridepublic Date convert(String str) {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");try {return simpleDateFormat.parse(str);} catch (ParseException e) {e.printStackTrace();}return null;}
}
在springmvc中配置添加转换器:方式一
<!-- 1、配置注解的适配器和映射器 --> <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
FormattingConversionServiceFactoryBean
<!-- 4、自定义参数类型绑定 --><bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><!-- 转换器 --><property name="converters"><list><!-- 日期类型转换 --><bean class="com.zwd.ssm.controller.converter.DateConverter"></bean></list></property></bean>
在springmvc中配置添加转换器:方式二(自学)
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer" ref="customBinder"></property>
</bean><!-- 自定义webBinder -->
<bean id="customBinder"class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"><property name="conversionService" ref="conversionService" />
</bean><!-- conversionService -->
<bean id="conversionService"class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><!-- 转换器 --><property name="converters"><list><bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/></list></property></bean>
问题
post乱码
在web.xml添加post乱码filter
在web.xml中加入:
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
get乱码
get乱码原因:tomcat编码和文件编码不一致。
对于get请求中文参数出现乱码解决方法有两个:
1、修改tomcat配置文件添加编码与工程编码一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
2、另外一种方法对参数进行重新编码:
String userName = new
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
springMVC和struts的区别
1、springMVC是基于方法开发的,struts2是基于类开发的。
springMVC将url和controller方法映射。映射成功后springMVC生成一个Handler对象,对象中值包括了一个method。方法执行结束,形参数据销毁。
2、springMVC可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。
3、经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts2建议使用jstl。
第二天
课程安排:
在商品查询和商品修改功能案例驱动下进行学习:包装类型pojo参数绑定集合类型的参数绑定:数组、list、map...商品修改添加校验,学习springMVC提供校验validation(使用的是hibernate校验框架)数据回显统一异常处理上传图片json数据交互restful支持拦截器
1、包装类型pojo参数绑定
1.1、需求
商品查询controller方法中实现商品查询条件传入。
1.2、实现方法
- 第一种方法:在形参中添加
HttpServletRequest
request参数,通过接受查询条件参数。 - 第二种方法:在形参中让包装类型的pojo接受查询条件参数。
1.3、包装类型pojo参数绑定
页面参数:
商品名称: input name="itemsCustom.name "
<form action="${pageContext.request.contextPath }/items/queryItems.action" method="post"> 查询条件: <table width="100%" border=1> <tr> <td>商品名称:<input name="itemsCustom.name"/></td><td><input type="submit" value="查询"/></td> </tr> </table>
包装类型pojo: ItemsCustom itemsCustom;
注意set和get方法要写!!
package com.zwd.ssm.po; /*** 商品信息包装类* @author Administrator**/ public class ItemsQueryVo {ItemsCustom itemsCustom;public ItemsCustom getItemsCustom() {return itemsCustom;}public void setItemsCustom(ItemsCustom itemsCustom) {this.itemsCustom = itemsCustom;} }
2、集合类型的参数绑定
2.1、数组
需求
在商品展示页面(itemsList.jsp)批量删除商品。
页面代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!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=UTF-8">
<title>查询商品列表</title><script type="text/javascript">function deleteItems(){//提交formdocument.itemsForm.action="${pageContext.request.contextPath}/items/deleteItems.action";document.itemsForm.submit();}function queryItems(){//提交formdocument.itemsForm.action="${pageContext.request.contextPath }/items/queryItems.action";document.itemsForm.submit();}
</script>
</head>
<body><formname="itemsForm"action="${pageContext.request.contextPath }/items/queryItems.action"method="post">查询条件:<table width="100%" border=1><tr><td>商品名称:<input name="itemsCustom.name" /></td><td><input type="button" value="查询" οnclick="queryItems()"/><input type="button" value="批量删除" οnclick="deleteItems()"/></td></tr></table>商品列表:<table width="100%" border=1><tr><td>选择</td><td>商品名称</td><td>商品价格</td><td>生产日期</td><td>商品描述</td><td>操作</td></tr><c:forEach items="${itemsList}" var="item"><tr><td><input type="checkbox" name="items_id" value="${item.id}"></input></td><td>${item.name }</td><td>${item.price }</td><td><fmt:formatDate value="${item.createtime}"pattern="yyyy-MM-dd HH:mm:ss" /></td><td>${item.detail }</td><td><ahref="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td></tr></c:forEach></table></form>
</body></html>
表现层实现
关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。
形参名称与标签的name值一致
controller方法定义:
页面定义:
2.2、List
需求
通常在需要批量提交数据时,将提交的数据绑定到List<pojo>
中,比如:成绩录入(录入多门课的成绩,然后批量提交)。
该例子需求:批量商品修改。修改多个商品信息,将多个商品信息一起提交到controller。
页面代码:editItemsQuery.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!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=UTF-8">
<title>查询商品列表</title><script type="text/javascript">function editItemsAllSubmit(){//提交formdocument.itemsForm.action="${pageContext.request.contextPath}/items/editItemsAllSubmit.action";document.itemsForm.submit();}function queryItems(){//提交formdocument.itemsForm.action="${pageContext.request.contextPath }/items/queryItems.action";document.itemsForm.submit();}
</script>
</head>
<body><formname="itemsForm"action="${pageContext.request.contextPath }/items/queryItems.action"method="post">查询条件:<table width="100%" border=1><tr><td>商品名称:<input name="itemsCustom.name" /></td><td><input type="button" value="查询" οnclick="queryItems()"/><input type="button" value="批量提交" οnclick="editItemsAllSubmit()"/></td></tr></table>商品列表:<table width="100%" border=1><tr><td>商品名称</td><td>商品价格</td><td>生产日期</td><td>商品描述</td></tr><c:forEach items="${itemsList}" var="item" varStatus="status"><tr><td><input name="itemsList[${status.index}].name" value="${item.name}"></input></td><td><input name="itemsList[${status.index}].price" value="${item.price}"></input></td><td><input name="itemsList[${status.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"></input></td><td><input name="itemsList[${status.index}].detail" value="${item.detail}"></input></td></tr></c:forEach></table></form>
</body></html>
表现层实现
使用List接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义list属性。
展示修改信息页面的controller:
/*** 5.批量修改商品信息页面:* @return*/@RequestMapping(value="/editItemsQuery",method={RequestMethod.GET,RequestMethod.POST})public ModelAndView editItemsQuery(ItemsQueryVo itemsQueryVo){List<ItemsCustom> itemsList = itemsService.findItemsList(itemsQueryVo);ModelAndView modelAndView = new ModelAndView();modelAndView.addObject("itemsList", itemsList);modelAndView.setViewName("items/editItemsQuery");return modelAndView;}
点击批量提交后的controller:
/*** 6、批量修改后的提交页面(批量提交):list参数绑定* @param itemsQueryVo* @return*/@RequestMapping(value="/editItemsAllSubmit")public String editItemsAllSubmit(ItemsQueryVo itemsQueryVo){return "redirect:editItemsQuery.action";}
形参类型:需要一个list集合来接收批量提交的数据。
页面定义:
2.3、map
也通过在包装pojo中定义map类型属性。
在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。
包装类中定义Map对象如下:
Public class QueryVo {private Map<String, Object> itemInfo = new HashMap<String, Object>();//get/set方法..
}
页面定义如下:
<tr>
<td>学生信息:</td>
<td>
姓名:<inputtype="text"name="itemInfo['name']"/>
年龄:<inputtype="text"name="itemInfo['price']"/>
.. .. ..
</td>
</tr>
Contrller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{System.out.println(queryVo.getStudentinfo());
}
3、服务端校验
3.1、校验理解
项目中,通常使用较多的是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。
服务端校验:
控制层controller:校验页面请求的参数的合法性。在服务端控制层controller校验,不区分客户端类型(浏览器,手机客户端,远程调用)
业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数。
持久层dao:一般是不校验的。
3.2、springmvc校验
springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。
校验思路:
页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。
具体需求:商品修改,添加校验(校验商品名称长度,生产日期的非空校验),如果校验出错,在商品修改页面显示错误信息。
3.3、环境准备
- 添加校验的jar包:
3.4、添加校验配置文件:CustomValidationMessages.properties
3.5、配置校验器:springmvc.xml
<!-- 5、配置校验器 --><bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"><!-- 校验器 --><property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property><!-- 指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties --><property name="validationMessageSource" ref="messageSource"></property></bean><!-- 校验错误信息配置文件 --><bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"><!-- 资源文件名 --><property name="basenames"><list><value>classpath:CustomValidationMessages</value></list></property><!-- 资源文件编码格式 --><!--<property name="fileEncodings" value="utf-8"></property>错误配置--><property name="defaultEncoding" value="utf-8"></property> <!-- 资源文件内容缓存时间 ,单位秒--><property name="cacheSeconds" value="120"></property></bean>
3.6、将校验器配置到处理器适配器中:springmvc.xml
配置方式1:
validator="validator"
<!-- 1、配置注解的处理器适配器和映射器 --> <mvc:annotation-driven conversion-service="conversionService" validator="validator"></mvc:annotation-driven>
配置方式2(自学):
<!-- 自定义webBinder --><bean id="customBinder"class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"><property name="validator" ref="validator" /></bean><!-- 注解适配器 --><beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer" ref="customBinder"></property></bean>
3.7、添加校验规则items.java
items.java
//message:错误输入的提示信息@Size(min=1,max=30,message="{items.name.length.error}")private String name;private Float price;private String pic;@NotNull(message="{items.createtime.isNull}")private Date createtime;
3.8、错误消息文件配置CustomValidationMessages
#配置错误提示信息
items.name.length.error=商品名称在1到30个字符之间
items.createtime.isNull=请输入商品的日期
3.9、在controller中捕获校验信息
**捕获校验信息:**在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult的形参,接收校验出错信息。
注意:@Validated和BindingResult形参是配对出现的,并且顺序是一前一后。
@Validated ItemsCustom itemsCustom,BindingResult bindingResult
/*** 7、点击提交后的操作:信息校验* @param id* @param itemsCustom* @return*///校验信息:在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult的形参,接收校验出错信息。//注意:@Validated和BindingResult形参是配对出现的,并且顺序是一前一后。@RequestMapping(value="/editItemsSubmit",method={RequestMethod.POST,RequestMethod.GET})public String editItemsSubmit(Integer id,@Validated ItemsCustom itemsCustom,BindingResult bindingResult) throws Exception{//获取校验错误信息if(bindingResult.hasErrors()){List<ObjectError> allErrors = bindingResult.getAllErrors();for (ObjectError objectError : allErrors) {System.out.println(objectError.getDefaultMessage());}}//获取提交的items,更新到数据库itemsService.updateItems(id, itemsCustom);return "forward:queryItems.action";}
3.10、在页面中显示错误信息
将错误信息传到页面:
List<ObjectError> allErrors = bindingResult.getAllErrors(); //将错误信息传导页面 model.addAttribute("allErrors", "allErrors");
/*** 7、点击提交后的操作:信息校验* @param id* @param itemsCustom* @return*///校验信息:在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult的形参,接收校验出错信息。//注意:@Validated和BindingResult形参是配对出现的,并且顺序是一前一后。@RequestMapping(value="/editItemsSubmit",method={RequestMethod.POST,RequestMethod.GET})public String editItemsSubmit(Integer id,Model model,@Validated ItemsCustom itemsCustom,BindingResult bindingResult) throws Exception{//获取校验错误信息if(bindingResult.hasErrors()){List<ObjectError> allErrors = bindingResult.getAllErrors();for (ObjectError objectError : allErrors) {System.out.println(objectError.getDefaultMessage());}//将错误信息传导页面model.addAttribute("allErrors", "allErrors");return null;}//获取提交的items,更新到数据库itemsService.updateItems(id, itemsCustom);return "forward:queryItems.action";}
在页面中获取错误信息
<!-- 显示错误信息 -->
<c:if test="${allErrors != null}"><c:forEach items="${allErrors}" var="error">${error.defaultMessage }<br/></c:forEach>
</c:if>
问题:获取到的校验信息乱码
https://blog.csdn.net/stloven5/article/details/53312012
资源文件编码格式配置错误
正确配置方式:
<!-- 资源文件编码格式 --><property name="fileEncodings"><props><prop key="classpath:CustomValidationMessages">UTF-8</prop></props></property>
或者直接配置:
<property name="defaultEncoding" value="utf-8"></property>
3.11、分组校验
需求:
在pojo中定义校验规则,而pojo是被多个controller所共用,当不同的controller方法对同一个pojo进行校验。但是每个controller方法需要不同的校验。
解决方法:
定义多个校验分组(其实是一个java接口),分组中定义有哪些规则。
每个controller方法使用不同的校验分组。
定义分组:接口定义
package com.zwd.ssm.controller.validation;
/*** 校验分组* @author Administrator**/
public interface ValidGroup1 {//此接口中不需要定义任何方法,仅是对不同的校验规则进行分组//此分组校验商品名称长度
}
在校验规则中添加分组
在controller方法上使用分组校验
3.12、校验注解
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
4、数据回显:
4.1、什么是数据回显
提交后,如果出现错误,将刚才提交的数据回显到刚才的提交的页面。
4.2、pojo数据回显方法:@ModelAttribute
1、springMVC默认对pojo数据进行回显。
pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)。
2、使用@ModelAttribute
可以指定pojo回显到页面在request中的key。页面就可以根据该key来取值。
3、@ModelAttribute
还可以将方法的返回值传到页面
/*** 商品分类* @return*///@ModelAttribute表示最终将方法返回值放在request中的key中@ModelAttribute(value="itemTypes")public Map<String,String> getItemTypes(){Map<String,String> itemTypes = new HashMap<String,String>();itemTypes.put("101", "数码");itemTypes.put("102", "母婴");return itemTypes;}
<td>商品名称:<input name="itemsCustom.name" />商品类型:<select name="itemTypes"><c:forEach items="${itemTypes}" var="itemType"><option value="${itemType.key}">${itemType.value}</option></c:forEach></select>
</td>
4.3、简单类型回显方法
对于简单数据类型,如:Integer、String、Float等使用Model将传入的参数再放到request域实现显示。
@RequestMapping(value="/editItems",method={RequestMethod.GET})public String editItems(Model model,Integer id)throws Exception{//传入的id重新放到request域model.addAttribute("id", id);
5、异常处理
5.1、异常处理思路
系统中异常包括两类,预期异常和运行异常RunTimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springMVC前端控制器交给异常处理器进行异常处理。如下图:
springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
5.2、自定义异常类
对不同的异常类型定义异常类,继承Exception。
package com.zwd.ssm.exception;
/*** 系统自定义的异常类:针对预期的异常,需要在程序中抛出此类异常。* @author Administrator**/
public class CustomException extends Exception {//异常信息private String message;public CustomException(String message){super(message);this.message = message;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}}
5.3、全局异常处理器
思路:
系统遇到异常,在程序中手动抛出,dao抛给service、service给controller,controller抛给前端控制器,前端控制器调用全局异常处理器。
全局异常处理器处理器思路:
解析出异常类型
如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示。
如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
必须继承HandlerExceptionResolver
package com.zwd.ssm.exception;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/*** 全局异常处理器* @author Administrator**/
public class CustomExceptionResolver implements HandlerExceptionResolver{/*** Object handler:处理器适配器要执行的handler(只有一个method)* Exception ex:系统抛出的异常*/@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse respnse, Object handler,Exception ex) {/* String message = null;
// 解析出异常类型
// 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示。if(ex instanceof CustomException){message = ex.getMessage();}
// 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)else{message="未知错误";}*///上面代码重写为:CustomException customException = null;if(ex instanceof CustomException){customException = new CustomException(ex.getMessage());}else{customException = new CustomException("未知错误");}//错误信息String message = customException.getMessage();ModelAndView modelAndView = new ModelAndView();//将错误信息传到页面modelAndView.addObject("message", message);//指向错误页面modelAndView.setViewName("error");return modelAndView;}}
5.4、错误页面
error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>错误页面</title>
</head>
<body>
错误页面
</body>
</html>
5.5、在springmvc中配置全局异常处理器
<!-- 6、配置全局异常处理器:只要实现了HandlerExceptionResolver接口,就是一个全局异常处理器 --><bean class="com.zwd.ssm.exception.CustomExceptionResolver"></bean>
5.6、异常测试
在controller、service、dao中任意一处需要手动抛出自定义异常。如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。
在商品修改的controller方法中抛出异常 :
在service中抛出异常:
如果与业务功能相关的异常,建议在service中抛出异常。
与业务功能没有关系的异常,建议在controller中抛出。
上边的功能,建议在service中抛出异常。
6、上传图片
6.1、需求
在修改商品页面,添加上传商品图片功能。enctype="multipart/form-data"
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action"
method="post" enctype="multipart/form-data">
6.2、导入jar包
6.3、springmvc中对多部件类型的解析
在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析。
在springmvc.xml中配置解析器:
<!-- 7、上传图片:配置多部件类型解析器--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 设置上传文件的最大尺寸为5MB --><property name="maxUploadSize" ><value>5242880</value></property></bean>
6.4、创建图片虚拟目录来存储图片
- 通过图形界面来创建:
在tomcat服务器的config/server.xml中添加配置
<Context docBase="G:\imgs" path="/pic" reloadable="true"/>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"><!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/><Context docBase="06.ssm" path="/06.ssm" reloadable="true" source="org.eclipse.jst.jee.server:06.ssm"/><Context docBase="G:\imgs" path="/pic" reloadable="true"/></Host>
**注意:**在图片虚拟目录中,一定将图片目录分级创建(提高i/o性能),一般我们采用按日期(年、月、日)进行分级创建。
6.5、上传图片代码
页面代码
<tr><td>商品图片</td><td><c:if test="${itemsCustom.pic !=null}"><img src="/pic/${itemsCustom.pic}" width=100 height=100/><br/></c:if><input type="file" name="items_pic"/> </td>
</tr>
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!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=UTF-8">
<title>修改商品信息</title></head>
<body> <!-- 显示错误信息 -->
<c:if test="${allErrors != null}"><c:forEach items="${allErrors}" var="error">${error.defaultMessage }<br/></c:forEach>
</c:if><form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action"
method="post" enctype="multipart/form-data">
<input type="hidden" name="id" value="${itemsCustom.id }"/>
修改商品信息:
<table width="100%" border=1>
<tr><td>商品名称</td><td><input type="text" name="name" value="${itemsCustom.name }"/></td>
</tr>
<tr><td>商品价格</td><td><input type="text" name="price" value="${itemsCustom.price }"/></td>
</tr><tr><td>商品生产日期</td><td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
</tr>
<tr><td>商品图片</td><td><c:if test="${itemsCustom.pic !=null}"><img src="/pic/${itemsCustom.pic}" width=100 height=100/><br/></c:if><input type="file" name="items_pic"/> </td>
</tr>
<tr><td>商品简介</td><td><textarea rows="3" cols="30" name="detail">${itemsCustom.detail }</textarea></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/>
</td>
</tr>
</table></form>
</body></html>
controller代码
MultipartFile items_pic
/*** 7、点击提交后的操作:上传图片* @param id* @param itemsCustom* @return*///MultipartFile:获取页面上传图片的信息@RequestMapping(value="/editItemsSubmit",method={RequestMethod.POST,RequestMethod.GET})public String editItemsSubmit(Integer id,Model model,@ModelAttribute(value="items") @Validated(value={ValidGroup1.class}) ItemsCustom itemsCustom,BindingResult bindingResult,MultipartFile items_pic) throws Exception{//获取校验错误信息if(bindingResult.hasErrors()){List<ObjectError> allErrors = bindingResult.getAllErrors();for (ObjectError objectError : allErrors) {System.out.println(objectError.getDefaultMessage());}//将错误信息传导页面model.addAttribute("allErrors", allErrors);return "items/editItems";}//上传图片if(items_pic != null && items_pic.getOriginalFilename()!= null && items_pic.getOriginalFilename()!=""){//存储图片的物理路径String pic_path = "G:\\imgs\\";//原始名称String originaleFilename = items_pic.getOriginalFilename();//新的图片名称String newFileName = UUID.randomUUID() + originaleFilename.substring(originaleFilename.lastIndexOf("."));//新图片File newFile = new File(pic_path+newFileName);//将内存中的数据写入磁盘items_pic.transferTo(newFile);//将新图片名称写到itemsCustom中itemsCustom.setPic(newFileName);}//获取提交的items,更新到数据库itemsService.updateItems(id, itemsCustom);return "forward:queryItems.action";}
7、json数据交互
7.1、 为什么要进行json数据交互
json数据格式在接口调用中、HTML页面中较常用,json格式比较简单,解析还比较方便。
比如:webService接口,传输json数据。
7.2、springmvc进行json交互
1、请求json、输出json,要求请求的是json串,所以在前端页面中需要将请求的内容转成json,不太方便。
2、请求key/value、输出json。此方法比较常用。
@RequestBody
作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。
@ResponseBody
作用:
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
7.3、环境准备
springmvc中使用jackson的包进行json转换(@RequestBody、@ResponseBody使用下边的包进行json转换)
上述包不适用,已更换为下面三个json包。
7.4、配置json转换器
注意:如果使用<mvc:annotation-driven />
则不用定义下边的内容。
<!--注解适配器 --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean></list></property></bean>
7.5、json测试
7.5.1、输入json,输出json
jsp页面
使用jQuery的ajax提交json串,对输出的json结构进行解析。
- 将jQuery文件放在WebRoot下:
jsp页面代码
<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%> <!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=utf-8"> <title>json交互测试</title> </head><script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script> <script type="text/javascript">//请求json输出jsonfunction requestJson(){$.ajax({type:'post',url:'${pageContext.request.contextPath }/requestJson.action',contentType:'application/json;charset=utf-8',//请求的数据格式是json串data:'{"name":"手机","price":999}',success:function(data){//data:返回的json串alert(data);}});}//请求key/value输出jsonfunction requestKV(){}</script> <body><input type="button" οnclick="requestJson()" value="请求json输出json"/><input type="button" οnclick="requestKV()" value="请求json输出json"/> </body> </html>
controller
package com.zwd.ssm.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.zwd.ssm.po.ItemsCustom;
/*** json的测试controller* @author Administrator**/
@Controller
public class JsonTextController {/*** 输入json(商品信息),输出json(商品信息)* @param itemsCustom* @return*///@RequestBody:将输入的json串转为java对象//@ResponseBody:将输出的java对象转为json串输出@RequestMapping("/requestJson")public @ResponseBody ItemsCustom requestJson(@RequestBody ItemsCustom itemsCustom){return itemsCustom;}
}
访问
http://localhost:8080/08.json/jsonTest.jsp
7.5.2、输入key/value,输出json
jsp页面
<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<!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=utf-8">
<title>json交互测试</title>
</head><script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">//请求json输出jsonfunction requestJson(){$.ajax({type:'post',url:'${pageContext.request.contextPath }/requestJson.action',//ContentType没指定将默认为:application/x-www-form-urlencodedcontentType:'application/json;charset=utf-8',//请求的数据格式是json串data:'{"name":"手机","price":999}',success:function(data){//data:返回的json串alert(data);}});}//请求key/value输出jsonfunction requestKV(){$.ajax({type:'post',url:'${pageContext.request.contextPath }/requestKV.action',//这里不用指定contentType,默认就是这里key/value的类型//contentType:'application/x-www-form-urlencoded',data:'name=手机&price=999',success:function(data){//data:返回的json串alert(data.name);}});}</script>
<body><input type="button" οnclick="requestJson()" value="请求json输出json"/><input type="button" οnclick="requestKV()" value="请求json输出json"/>
</body>
</html>
controller
package com.zwd.ssm.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.zwd.ssm.po.ItemsCustom;
/*** json的测试controller* @author Administrator**/
@Controller
public class JsonTextController {/*** 输入json(商品信息),输出json(商品信息)* @param itemsCustom* @return*///@RequestBody:将输入的json串转为java对象//@ResponseBody:将输出的java对象转为json串输出@RequestMapping("/requestJson")public @ResponseBody ItemsCustom requestJson(@RequestBody ItemsCustom itemsCustom){return itemsCustom;}/*** 请求key/value,输出json* @param itemsCustom* @return*/@RequestMapping("/requestKV")public @ResponseBody ItemsCustom requestKV(ItemsCustom itemsCustom){return itemsCustom;}
}
访问
http://localhost:8080/08.json/jsonTest.jsp
报错问题
问题已在上面更改。
jquery-1.4.4.min.js找不到,404
解决:js文件放错位置。应放在WebRoot下。
org.springframework.web.HttpMediaTypeNotSupportedException:
Content type ‘application/json;charset=utf-8’ not supported
https://blog.csdn.net/fpxty/article/details/72835993
解决:json包版本太低,更换json包。
8、RESTful支持
8.1、什么是RESTful
RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
RESTful(即Representational State Transfer的缩写)其实是一个开发理念,是对http的很好的诠释。
1、对url进行规范,写RESTful格式的url
非REST的url:http://…/queryItems.action?id=001&type=T01
REST的url风格:http://…/items/001
特点:url简洁,将参数通过url传到服务端
2、http的方法规范
不管是删除、添加、更新。。使用url是一致的,如果进行删除,需要设置http的方法为delete,同理添加后台controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。
3、对http的contentType规范
请求时指定contentType,要json数据,设置成json格式的type。。
8.2、REST测试
需求
查询商品信息,返回json数据。
controller
package com.zwd.ssm.controller;import javax.annotation.Resource;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.zwd.ssm.po.ItemsCustom;
import com.zwd.ssm.service.ItemsService;/*** RESTful测试* @author Administrator**/
@Controller
public class RestfulController {@Resource(name="itemsService")private ItemsService itemsService;/*** 查询商品信息:restful风格的url* @param id* @return* @throws Exception*///{id}:表示占位符,通过@PathVariable("id")获取占位符中的参数。//如果占位符中的名称和形参名称一致,在@PathVariable中可以不指定名称@RequestMapping("/restfulItemsquery/{id}")public @ResponseBody ItemsCustom restfulItemsquery(@PathVariable("id") Integer id) throws Exception{ItemsCustom itemsCustom = itemsService.findItemsById(id);return itemsCustom;}// @RequestMapping("/restfulItemsquery/{id}/{type}")
// public @ResponseBody ItemsCustom restfulItemsquery1(@PathVariable("id") Integer id,@PathVariable("type") String aaa) throws Exception{// ItemsCustom itemsCustom = itemsService.findItemsById(id);
// return itemsCustom;
// }
}
REST方法的前端控制器配置
因为之前把url-pattern设置成*.action,所以使用restful风格的url(http://localhost:8080/08.json/restfulItemsquery/1)直接访问上面controller时,会发生404错误,找不到对应的url的handler。改成’/'即可访问。
HTTP Status 404 - /08.json/restfulItemsquery/1
<!-- 2、配置springmvc前端控制器 --><!-- The front controller of this Spring Web application, responsible for handling all application requests --><servlet><servlet-name>springDispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><!-- <servlet-mapping><servlet-name>springDispatcherServlet</servlet-name><url-pattern>*.action</url-pattern></servlet-mapping> --><!-- 使用restful,需要将url-pattern设置成 '/',否则无法访问,因为上述只能访问.action后缀的url --><servlet-mapping><servlet-name>springDispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
对静态资源的访问
http://localhost:8080/08.json/js/jquery-1.4.4.min.js
如果/这样设置,那么在访问静态资源的时候会发生404错误。因为根据地址找不到相应的handler,需要在springmvc.xml中添加对静态资源的访问。
<!-- 8、对静态资源的访问:如果<url-pattern>/</url-pattern>这样设置的,那么再访问静态资源的时候会发生404错误。因为根据地址找不到相应的handler,需要添加对静态资源的访问静态资源包括:js、css、img.... --><mvc:resources location="/js/" mapping="/js/**"/>
报错问题
在添加<mvc:resources location="/js/" mapping="/js/**"/>
配置后,启动tomcat异常:
DEBUG [localhost-startStop-1] - Original ConversionService attempt
failed - ignored since PropertyEditor based conversion eventually
succeeded org.springframework.core.convert.ConversionFailedException:
Failed to convert from type java.util.ArrayList<?> to type
java.util.List<org.springframework.core.io.Resource> for value
‘[/js/]’; nested exception is
org.springframework.core.convert.ConverterNotFoundException: No
converter found capable of converting from type java.lang.String to
type org.springframework.core.io.Resource
解决参考地址:
https://blog.csdn.net/jevonsCSDN/article/details/60577714
9、拦截器
9.1、拦截器的定义
继承HandlerInterceptor
接口:
package com.zwd.ssm.interceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;/*** 拦截器例子* @author Administrator**/
public class HandlerInterceptor1 implements HandlerInterceptor{/*** 1、进入Handler方法之前执行*///应用场景:用于身份认证、身份授权//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行@Overridepublic boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {//return false表示拦截,不再向下执行handler方法//return true表示放行return false;}/*** 2、进入handler方法之后,返回modelAndView之前执行。*///应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图@Overridepublic void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {}/*** 3、handler执行完成后执行此方法*///应用场景:统一异常处理,统一日志处理@Overridepublic void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {}}
9.2、拦截器配置springmvc.xml
方式一:针对HandlerMapping进行拦截设置
springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的handler最终使用该拦截器。一般不推荐使用。
<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"><property name="interceptors"><list><ref bean="handlerInterceptor1"/><ref bean="handlerInterceptor2"/></list></property>
</bean><bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/><bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
方式二:配置类似全局的拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
<!-- 9、全局拦截器配置 --> <mvc:interceptors><!-- 多个拦截器,顺序执行 --><mvc:interceptor><!-- /**:表示拦截所有url包括子url路径 --><mvc:mapping path="/**"/><bean class="com.zwd.ssm.interceptor.HandlerInterceptor1"></bean></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.zwd.ssm.interceptor.HandlerInterceptor2"></bean></mvc:interceptor></mvc:interceptors>
9.3、拦截器的测试
需求
测试多个拦截器各各方法执行时机。
编写两个拦截
HandlerInterceptor1
package com.zwd.ssm.interceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;/*** 拦截器例子* @author Administrator**/
public class HandlerInterceptor1 implements HandlerInterceptor{/*** 进入Handler方法之前执行*///应用场景:用于身份认证、身份授权//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行@Overridepublic boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {//return false表示拦截,不再向下执行handler方法//return true表示放行System.out.println("HandlerInterceptor1...preHandle");return true;}/*** 进入handler方法之后,返回modelAndView之前执行。*///应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图@Overridepublic void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {System.out.println("HandlerInterceptor1...postHandle");}/*** handler执行完成后执行此方法*///应用场景:统一异常处理,统一日志处理@Overridepublic void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {System.out.println("HandlerInterceptor1...afterCompletion");}}
HandlerInterceptor2
package com.zwd.ssm.interceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;/*** 拦截器例子* @author Administrator**/
public class HandlerInterceptor2 implements HandlerInterceptor{/*** 进入Handler方法之前执行*///应用场景:用于身份认证、身份授权//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行@Overridepublic boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {//return false表示拦截,不再向下执行handler方法//return true表示放行System.out.println("HandlerInterceptor2...preHandle");return true;}/*** 进入handler方法之后,返回modelAndView之前执行。*///应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图@Overridepublic void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {System.out.println("HandlerInterceptor2...postHandle");}/*** handler执行完成后执行此方法*///应用场景:统一异常处理,统一日志处理@Overridepublic void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {System.out.println("HandlerInterceptor2...afterCompletion");}
}
拦截器在springmvc.xml中的配置如9.2方式二。
拦截器1和拦截器2都放行
HandlerInterceptor1…preHandle
HandlerInterceptor2…preHandle
HandlerInterceptor2…postHandle
HandlerInterceptor1…postHandle
HandlerInterceptor2…afterCompletion
HandlerInterceptor1…afterCompletion
总结:
preHandle方法按顺序执行
postHandle和afterCompletion按拦截器配置的逆向顺序执行。
拦截器1放行、拦截器2不放行
HandlerInterceptor1…preHandle
HandlerInterceptor2…preHandle
HandlerInterceptor1…afterCompletion
总结:
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle都不会执行。
拦截器1不放行、拦截器2不放行
HandlerInterceptor1…preHandle
HandlerInterceptor1…preHandle
总结:
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。
小结
根据测试结果,对拦截器应用进行总结。
比如:统一日志处理拦截器,需要该拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)
9.4、拦截器应用:实现登录认证
需求
1、用户请求url
2、拦截器进行拦截校验
如果请求的url是公开地址(无需登录即可访问的url),让放行
如果用户session不存在跳转到登录页面
如果用户session存在放行,继续操作
登录页面:login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>系统登陆</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/login.action" method="post">
用户账号:<input type="text" name="username" /><br/>
用户密码 :<input type="password" name="password" /><br/>
<input type="submit" value="登陆"/>
</form>
</body>
</html>
登录的controller方法
LoginController.java
package com.zwd.ssm.controller;import javax.servlet.http.HttpSession;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;/*** 登录* @author Administrator**/
@Controller
public class LoginController {/*** 登录* @param session* @param username* @param password* @return*/@RequestMapping("/login")public String login(HttpSession session,String username,String password){//调用service进行身份认证...session.setAttribute("username", username);//重定向到商品查询页面return "redirect:/items/queryItems.action";}/*** 退出登录* @param session* @return*/@RequestMapping("/logout")public String logout(HttpSession session){//清除sessionsession.invalidate();return "redirect:/items/queryItems.action";}
}
登录认证拦截实现
package com.zwd.ssm.interceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;/*** 拦截器例子* @author Administrator**/
public class LoginInterceptor implements HandlerInterceptor{/*** 用户身份验证*///应用场景:用于身份认证、身份授权//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {//获取url地址StringBuffer url = request.getRequestURL();//判断该地址是否是公开地址(实际项目中公开地址需要写到配置文件中),这里是登录页面的地址if(url.indexOf("login.action")>=0){//是登录页面,放行return true;}if(request.getSession() != null && request.getSession().getAttribute("username") != null){//不是登录页面,但用户已经登录,放行return true;}//否则:不是登录连接并且session为空:跳转到登录页面,不放行request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);return false;}/*** 进入handler方法之后,返回modelAndView之前执行。*///应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图@Overridepublic void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {System.out.println("HandlerInterceptor2...postHandle");}/*** handler执行完成后执行此方法*///应用场景:统一异常处理,统一日志处理@Overridepublic void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {System.out.println("HandlerInterceptor2...afterCompletion");}
}
拦截器配置:springmvc.xml
<!-- 9、全局拦截器配置 --> <mvc:interceptors><!-- 多个拦截器,顺序执行 --><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.zwd.ssm.interceptor.LoginInterceptor"></bean></mvc:interceptor><mvc:interceptor><!-- /**:表示拦截所有url包括子url路径 --><mvc:mapping path="/**"/><bean class="com.zwd.ssm.interceptor.HandlerInterceptor1"></bean></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.zwd.ssm.interceptor.HandlerInterceptor2"></bean></mvc:interceptor></mvc:interceptors>
访问
http://localhost:8080/08.json/items/queryItems.action
框架-springmvc(ssm整合)相关推荐
- SSM框架:SSM整合
SSM框架:SSM整合 文章目录 前言 SSM整合 0. 环境搭建 1.环境要求 2.数据库环境 3.基本环境搭建 1.依赖 2.静态资源导出问题 底层 1. SSM整合:Mybatis层 整合dao ...
- ajax在ssm中的使用,Ajax 框架之SSM整合框架实现ajax校验
刚学习了ssm框架,ajax校验成功,分享下 1.导入jar包 2.配置spring-servlet.xml text/html;charset=UTF-8 text/json;charset=UTF ...
- mybatis+spring+springmvc ssm整合
文章目录 mybatis 开发我的第一个mybatis程序 关于mybatis的核心API:SqlSession对象. mybatis连接数据库操作 log4j jackson parameterTy ...
- springMVC——SSM整合(IDEA 搭建简单 ssm 框架最详细最简单教程)
为开发一个测试程序,特搭建一个简单的ssm框架,因为网上看到很多都是比较老旧的教程,很多包都不能用了,eclipes搭建并且其中还附带了很多的其他东西,所以特此记录一下mac中idea搭建过程. 以下 ...
- 【SSM】SSM整合
文章目录 SSM整合项目视频 项目功能点 技术点 设置maven 引入项目依赖的jar包 引入bootstrap前端框架 编写ssm整合的关键配置文件 web.xml配置 springMVC的配置文件 ...
- java框架ssm整合_SSM三大框架整合详细教程(Spring+SpringMVC+MyBatis)
使用 SSM ( Spring . SpringMVC 和 Mybatis )已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方.之前没 ...
- SSM(Spring+SpringMVC+Mybatis)框架环境搭建(整合步骤)(一)
SSM(Spring+SpringMVC+Mybatis)框架环境搭建(整合步骤)(一) 1. 前言 最近在写毕设过程中,重新梳理了一遍SSM框架,特此记录一下. 附上源码:https://gitee ...
- SpringMvc框架及SSM框架整合
SpringMvc框架及SSM框架整合 一.SpringMvc相关知识 1.Spring和SpringMvc的关系 1.1.Spring是IOC和AOP的容器框架,SpringMVC是基于Spri ...
- 基于Maven+SpringMVC+Spring+MyBatis+Layui整合框架,超详细的SSM整合❤️
人生有太多不如意,我们要学会去努力 参考文档:layUI文档:spring家族文档:mybatis文档 前言:SSM 整合 整合的思路是: 先创建spring框架 通过spring整合spring m ...
- SpringMVC学习06之SSM整合(一)
复习 我的环境 环境: IDEA MySQL 5.7.34 Tomcat 8 Maven 3.8.3 一.SSM整合 要求: 需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis ...
最新文章
- CowNew开源团队新书《自己动手写开发工具》隆重上市
- 2016年第七届蓝桥杯决赛Java本科B组试题解析
- zk如何实现watch
- python写文件追加 按行追加_Python3 自学第14天:文件操作,文件句柄,上下文管理器...
- 马逊s3云存储接口_利用 S3tests 测试 S3 接口兼容性
- 爱创课堂每日一题第四十天- 说说你对语义化的理解?
- 一、后台首页index.php【dedecms后台源码分析】
- 跟着老桂学ASP.NET Core 2.0
- Tomcat 全攻略
- RF工具ride使用
- 类似纪念碑谷的unity2d素材包_《纪念碑谷》:引领小清新风格的2.5D插画风游戏...
- 全网首发:以字型为例,一维表示的二维数组矩阵,以易理解的方式旋转90、-90
- access 知乎 窗体_ACCESS数据可视化之路
- 数学差考研考计算机专业,2021考研数学基础差,这4大方法让你快速上手_计算机专业考研...
- Deep Learning for Image and Point Cloud Fusionin Autonomous Driving: A Review
- python连连看小游戏_python tkinter实现连连看游戏
- 乐视尚酷版无线手柄PC驱动 手柄通用驱动教程
- 自动备份Linux上的博客数据到坚果云
- 小说作者推荐:忘却的悠合集
- 国内首部《数字货币词典》在新莫干山会议上启动,巴比特智库担任主编单位...