框架-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框架。

框架-springmvc(ssm整合)_第1张图片

1.2、什么是MVC

​ MVC是一个设计模式,MVC在b/s系统下的应用:

框架-springmvc(ssm整合)_第2张图片

1.3、springMVC框架

框架-springmvc(ssm整合)_第3张图片

第一步:发起请求到 前端控制器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 Transfer
    
    Source Server         : ZWD
    Source Server Version : 50711
    Source Host           : localhost:3306
    Source Database       : mybatis
    
    Target Server Type    : MYSQL
    Target Server Version : 50711
    File Encoding         : 65001
    
    Date: 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)

框架-springmvc(ssm整合)_第4张图片

2.2、配置前端控制器

​ 在类路径下添加文件:springmvc.xml

​ 在web.xml文件中配置前端控制器。


<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>
  

  <servlet>
  	<servlet-name>springmvcservlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
 
 	
 	<init-param>
 		<param-name>contextConfigLocationparam-name>
 		<param-value>classpath:springmvc.xmlparam-value>
 	init-param>
  servlet>
  
  <servlet-mapping>
  	<servlet-name>springmvcservlet-name>
  	
  	<url-pattern>*.actionurl-pattern>
  servlet-mapping>
  

  
  
  <welcome-file-list>
    <welcome-file>index.htmlwelcome-file>
    <welcome-file>index.htmwelcome-file>
    <welcome-file>index.jspwelcome-file>
    <welcome-file>default.htmlwelcome-file>
    <welcome-file>default.htmwelcome-file>
    <welcome-file>default.jspwelcome-file>
  welcome-file-list>
web-app>

2.3、配置处理其适配器

​ 在类路径下的springmvc.xml中配置处理器适配器。


<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

  
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">bean>      



beans>

SimpleControllerHandlerAdapter:支持实现Controller的Handler。

框架-springmvc(ssm整合)_第5张图片

框架-springmvc(ssm整合)_第6张图片

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 {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		System.out.println("进来。");
		//调用service
		List<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);
		
		//返回ModelAndView
		ModelAndView 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"%>




查询商品列表

 
查询条件:
商品列表:
商品名称 商品价格 生产日期 商品描述 操作
${item.name } ${item.price } ${item.detail } 修改

2.7、配置处理器映射器

​ 在类路径下的springmvc.xml中配置:


	
	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">bean>
	
	
	<bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1">bean>

2.8、配置视图解析器

​ 在springmvc.xml中配置视图解析器。


	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">bean>

​ 整个springmvc.xml的配置。


<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

  
	<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">bean>  
	    

	
	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">bean>
	
	
	<bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1">bean>
	

	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">bean>

beans>

2.9、访问页面

http://localhost:8080/01.springmvcFirst/queryItems.action

3、非注解的处理器映射器和适配器

3.1、非注解的处理器映射器

类型1:BeanNameUrlHandlerMapping


	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> 	 bean>
	
	<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">itemsControllerprop>
				<prop key="/queryItems2.action">itemsControllerprop>
			props>
		property>
	bean>

<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

  
	<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">bean>  
	    

	
	
	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">bean>
	
	<bean id="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1">bean>
	
	
	<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">itemsControllerprop>
				<prop key="/queryItems2.action">itemsControllerprop>
			props>
		property>
	bean>


	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">bean>

beans>

前端映射器会找到对应url使用的处理器映射器,能使用哪个就使用哪个。

3.2、非注解的适配器

类型1:SimpleControllerHandlerAdapter


<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 {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		//调用service
		List<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);
		
		//返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();
		//相当于request的setAttribute,在jsp页面中通过itemsList获取数据
		modelAndView.addObject("itemsList", itemsList);
		
		//指定视图
		modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
		
		return modelAndView;
	}
}

类型2:HttpRequestHandlerAdapter


<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 {

	@Override
	public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		//调用service
		List<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(ssm整合)_第7张图片

​ 前端控制器从上边的文件中加载处理器映射器、适配器、视图解析器等组件,如果不在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约束。


	
	  
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	bean>
	
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
	bean>
	
	
	<mvc:annotation-driven>mvc:annotation-driven>

<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">


	
	  
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	bean>
	
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
	bean>
	
	
	<mvc:annotation-driven>mvc:annotation-driven>


	
	<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 {

		//调用service
		List<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


	

<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()

框架-springmvc(ssm整合)_第8张图片

第二步:前端控制器调用处理器映射器。根据url查找handler

框架-springmvc(ssm整合)_第9张图片

第三步:根据handler查找对应的处理器适配器,并调用该适配器执行该handler返回ModelAndView

在这里插入图片描述

在这里插入图片描述

第四步:视图渲染。将model数据填充到request域。

视图解析得到view。

在这里插入图片描述

框架-springmvc(ssm整合)_第10张图片

框架-springmvc(ssm整合)_第11张图片

6、入门程序小结

前端控制器


  <servlet>
    <servlet-name>springmvcservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
    
      <param-name>contextConfigLocationparam-name>
      <param-value>classpath:springmvc.xmlparam-value>
    init-param>
  servlet>
  <servlet-mapping>
    <servlet-name>springmvcservlet-name>
    
    <url-pattern>*.actionurl-pattern>
  servlet-mapping>

处理器映射器

非注解的处理器映射器(两种):BeanNameUrlHandlerMappingSimpleUrlHandlerMapping


	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> 	 bean>
	
	<bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1">	bean>



	<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">itemsControllerprop>
				<prop key="/queryItems2.action">itemsControllerprop>
			props>
		property>
	bean>

处理器适配器

非注解的处理器适配器(两种):SimpleControllerHandlerAdapterHttpRequestHandlerAdapter


<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">bean> 


<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
bean>

注解的处理器映射器和适配器


	
	  
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	bean>
	
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
	bean>
	
	
	<mvc:annotation-driven>mvc:annotation-driven>

框架-springmvc(ssm整合)_第12张图片

视图解析器


	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/items">property>
		<property name="suffix" value=".jsp">property>
	bean>
		//在视图解析器中配置前缀和后缀
		//
		//
		request.getRequestDispatcher("items/itemsList").forward(request, response);
		

7、springMVC和mybatis整合

7.1、需求

​ 使用springMVC和mybatis完成商品列表的查询。

7.2、整合思路

​ springmvc和mybatis的系统架构

框架-springmvc(ssm整合)_第13张图片

第一步:整合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。

框架-springmvc(ssm整合)_第14张图片

  • 在类路径下创建日志文件: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
    

框架-springmvc(ssm整合)_第15张图片

7.4、整合dao

sqlMapConfig.xml

  • 创建sqlMapConfig.xml文件:config->mybatis->sqlMapConfig.xml

    
    
    
    <configuration>
    	
    	
    	<typeAliases>
    		
    		<package name="com.zwd.ssm.po"/>
    		
    	typeAliases>
    	
    	
    		
    
    configuration>
    

applicationContext_dao.xml

mapper批量扫描器:MapperScannerConfigurer
  • 创建applicationContext.xml文件:config->mybatis->applicationContext.xml

    
    <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.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
            
       
    	 
    	<context:property-placeholder location="classpath:db.properties"/> 
    	
    	<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>
    
    	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    		
    		<property name="dataSource" ref="dataSource">property>
    		
    		<property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml">property>
    	bean>
    
    	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    		
    		<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



<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>
	
	
	<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;
	
	@Override
	public List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception {
		return itemsMapper.findItemsList(itemsVo);
	}
}

使用xml配置管理service

applicationContext_service.xml

<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
      
	<bean id="itemsService" class="com.zwd.ssm.service.impl.ItemsServiceImpl">bean>	   
beans>

使用xml配置管理事务

applicationContext_tx.xml

<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">


	
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource">property>
	bean>
	
	
	<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>
        
      
    <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


<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.ssmdisplay-name>
  
  
  <servlet>
    <servlet-name>springmvcservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
    
      <param-name>contextConfigLocationparam-name>
      <param-value>classpath:springmvc.xmlparam-value>
    init-param>
  servlet>
  <servlet-mapping>
    <servlet-name>springmvcservlet-name>
    
    <url-pattern>*.actionurl-pattern>
  servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.htmlwelcome-file>
    <welcome-file>index.htmwelcome-file>
    <welcome-file>index.jspwelcome-file>
    <welcome-file>default.htmlwelcome-file>
    <welcome-file>default.htmwelcome-file>
    <welcome-file>default.jspwelcome-file>
  welcome-file-list>
web-app>

配置springmvc.xml


<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
      
      <context:component-scan base-package="com.zwd.ssm.controller">context:component-scan>
      
      <mvc:annotation-driven>mvc:annotation-driven>
      
	  
	  <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"%>




查询商品列表

 
查询条件:
商品列表:
商品名称 商品价格 生产日期 商品描述 操作
${item.name } ${item.price } ${item.detail } 修改

编写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("成功!");
		// 调用service
		List<ItemsCustom> itemsList = itemsService.findItemsList(null);

		// 返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();
		// 相当于request的setAttribute,在jsp页面中通过itemsList获取数据
		modelAndView.addObject("itemsList", itemsList);

		// 指定视图
		modelAndView.setViewName("/itemsList");

		return modelAndView;
	}
}

配置spring容器的监听器web.xml


	<context-param>
		<param-name>contextConfigLocationparam-name>
		<param-value>/WEB-INF/classes/spring/applicationContext_*.xmlparam-value>
	context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
	listener>

<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.ssmdisplay-name>


	<context-param>
		<param-name>contextConfigLocationparam-name>
		<param-value>/WEB-INF/classes/spring/applicationContext_*.xmlparam-value>
	context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
	listener>
	

  <servlet>
    <servlet-name>springmvcservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
    
      <param-name>contextConfigLocationparam-name>
      <param-value>classpath:spring/springmvc.xmlparam-value>
    init-param>
  servlet>
  <servlet-mapping>
    <servlet-name>springmvcservlet-name>
    
    <url-pattern>*.actionurl-pattern>
  servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.htmlwelcome-file>
    <welcome-file>index.htmwelcome-file>
    <welcome-file>index.jspwelcome-file>
    <welcome-file>default.htmlwelcome-file>
    <welcome-file>default.htmwelcome-file>
    <welcome-file>default.jspwelcome-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;
	@Autowired
	private ItemsMapperExample ItemsMapperExample;
	
	/**
	 * 查询商品信息
	 */
	@Override
	public List<ItemsCustom> findItemsList(ItemsVo itemsVo) throws Exception {
		return itemsMapper.findItemsList(itemsVo);
	}

	/**
	 * 查询商品信息
	 */
	@Override
	public ItemsCustom findItemsById(Integer id) {
		Items items = ItemsMapperExample.selectByPrimaryKey(id);
		//中间对商品进行业务处理
		//...
		//将所有信息封装到items的扩展类ItemsCustom中
		ItemsCustom itemsCustom = new ItemsCustom();
		//将items的属性值拷贝到itemsCustom中
		BeanUtils.copyProperties(items, itemsCustom);
		return itemsCustom;
	}

	/**
	 * 查询商品信息
	 */
	@Override
	public 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"%>

<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><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"%>

<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("成功!");
		// 调用service
		List<ItemsCustom> itemsList = itemsService.findItemsList(null);

		// 返回ModelAndView
		ModelAndView 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);
		
		//返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();
		
		modelAndView.addObject("itemsCustom", itemsCustom);
		modelAndView.setViewName("items/editItems");
		
		return modelAndView;
	}
	
	/**
	 * 修改提交商品信息
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/editItemsSubmit")
	public ModelAndView editItemsSubmit() throws Exception{
		//获取提交的items,更新到数据库
		
		//返回ModelAndView
		ModelAndView 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);
		
		//返回ModelAndView
		ModelAndView 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类中定义成员变量接收。

框架-springmvc(ssm整合)_第16张图片

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);
		
		//返回ModelAndView
		ModelAndView 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值:

框架-springmvc(ssm整合)_第17张图片

形参ItemsCustom中的属性名称:

框架-springmvc(ssm整合)_第18张图片

11.5、自定义参数类型绑定实现日期类型绑定

​ 对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。

框架-springmvc(ssm整合)_第19张图片

自定义日期类型转换

需要实现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日期类型
	@Override
	public 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中配置添加转换器:方式一

     
 <mvc:annotation-driven conversion-service="conversionService">mvc:annotation-driven>

FormattingConversionServiceFactoryBean


	<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>
	

<bean id="customBinder"
		class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
	<property name="conversionService" ref="conversionService" />
bean>


<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>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-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 "

    查询条件:
    商品名称:
  • 包装类型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"%>




查询商品列表





	
		查询条件:
		
商品名称:
商品列表:
选择 商品名称 商品价格 生产日期 商品描述 操作
${item.name } ${item.price } ${item.detail } 修改

表现层实现

​ 关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。

形参名称与标签的name值一致

​ controller方法定义:

框架-springmvc(ssm整合)_第20张图片

​ 页面定义:

框架-springmvc(ssm整合)_第21张图片

2.2、List

需求

​ 通常在需要批量提交数据时,将提交的数据绑定到List中,比如:成绩录入(录入多门课的成绩,然后批量提交)。

​ 该例子需求:批量商品修改。修改多个商品信息,将多个商品信息一起提交到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"%>




查询商品列表





	
查询条件:
商品名称:
商品列表:
商品名称 商品价格 生产日期 商品描述
">

表现层实现

​ 使用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集合来接收批量提交的数据。

框架-springmvc(ssm整合)_第22张图片

页面定义:

框架-springmvc(ssm整合)_第23张图片

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>
姓名:
年龄:
.. .. ..
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包:

框架-springmvc(ssm整合)_第24张图片

3.4、添加校验配置文件:CustomValidationMessages.properties

3.5、配置校验器:springmvc.xml


	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
		
		<property name="providerClass" value="org.hibernate.validator.HibernateValidator">property>
		
		<property name="validationMessageSource" ref="messageSource">property>
	bean>
	
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		
		<property name="basenames">
			<list>
				<value>classpath:CustomValidationMessagesvalue>
			list>
		property>
		
		
        <property name="defaultEncoding" value="utf-8">property> 
		
		<property name="cacheSeconds" value="120">property>
	bean>

3.6、将校验器配置到处理器适配器中:springmvc.xml

配置方式1:

validator="validator"

  
	<mvc:annotation-driven conversion-service="conversionService" validator="validator">mvc:annotation-driven>

配置方式2(自学):


	<bean id="customBinder"
		class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
		<property name="validator" ref="validator" />
	bean>


	<bean
		class="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";
    	}
    
  • 在页面中获取错误信息



	
		${error.defaultMessage }

问题:获取到的校验信息乱码

https://blog.csdn.net/stloven5/article/details/53312012

资源文件编码格式配置错误

正确配置方式:


	<property name="fileEncodings">
		<props><prop key="classpath:CustomValidationMessages">UTF-8prop>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 {
	//此接口中不需要定义任何方法,仅是对不同的校验规则进行分组
	//此分组校验商品名称长度
}

在校验规则中添加分组

框架-springmvc(ssm整合)_第25张图片

在controller方法上使用分组校验

框架-springmvc(ssm整合)_第26张图片

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来取值。

框架-springmvc(ssm整合)_第27张图片

​ 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(ssm整合)_第28张图片

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:系统抛出的异常
	 */
	@Override
	public 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"%>




错误页面


错误页面


5.5、在springmvc中配置全局异常处理器


	<bean class="com.zwd.ssm.exception.CustomExceptionResolver">bean>

5.6、异常测试

​ 在controller、service、dao中任意一处需要手动抛出自定义异常。如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。

​ 在商品修改的controller方法中抛出异常 :

框架-springmvc(ssm整合)_第29张图片

​ 在service中抛出异常:

框架-springmvc(ssm整合)_第30张图片

如果与业务功能相关的异常,建议在service中抛出异常。

与业务功能没有关系的异常,建议在controller中抛出。

上边的功能,建议在service中抛出异常。

6、上传图片

6.1、需求

​ 在修改商品页面,添加上传商品图片功能。enctype="multipart/form-data"

6.2、导入jar包

框架-springmvc(ssm整合)_第31张图片

6.3、springmvc中对多部件类型的解析

​ 在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析。

​ 在springmvc.xml中配置解析器:


	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		
		<property name="maxUploadSize" >
			<value>5242880value>
		property>
	bean>

6.4、创建图片虚拟目录来存储图片

  • 通过图形界面来创建:

框架-springmvc(ssm整合)_第32张图片

  • 在tomcat服务器的config/server.xml中添加配置

    <Context docBase="G:\imgs" path="/pic" reloadable="true"/>
    
      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
    
            
            
    
            
            <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、上传图片代码

页面代码


	商品图片
	
		
			
			
<%@ 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"%>

<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><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交互

框架-springmvc(ssm整合)_第33张图片

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转换)

框架-springmvc(ssm整合)_第34张图片

​ 上述包不适用,已更换为下面三个json包。

框架-springmvc(ssm整合)_第35张图片

7.4、配置json转换器

注意:如果使用则不用定义下边的内容。


	<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下:

框架-springmvc(ssm整合)_第36张图片

  • jsp页面代码

    <%@ page language="java" contentType="text/html; charset=utf-8"
    	pageEncoding="utf-8"%>
    
    
    
    
    json交互测试
    
    
    
    
    
    	
    	
    
    
    
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

框架-springmvc(ssm整合)_第37张图片

框架-springmvc(ssm整合)_第38张图片

7.5.2、输入key/value,输出json

jsp页面
<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>




json交互测试





	
	


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下。

框架-springmvc(ssm整合)_第39张图片

  • 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

	
	
	<servlet>
		<servlet-name>springDispatcherServletservlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
		<init-param>
			<param-name>contextConfigLocationparam-name>
			<param-value>classpath:spring/springmvc.xmlparam-value>
		init-param>
		<load-on-startup>1load-on-startup>
	servlet>


	
	
	<servlet-mapping>
		<servlet-name>springDispatcherServletservlet-name>
		<url-pattern>/url-pattern>
	servlet-mapping> 

对静态资源的访问

http://localhost:8080/08.json/js/jquery-1.4.4.min.js

​ 如果/这样设置,那么在访问静态资源的时候会发生404错误。因为根据地址找不到相应的handler,需要在springmvc.xml中添加对静态资源的访问。


	<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 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方法之前执行
	 */
	//应用场景:用于身份认证、身份授权
	//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		//return false表示拦截,不再向下执行handler方法
		//return true表示放行
		return false;
	}
	

	/**
	 * 2、进入handler方法之后,返回modelAndView之前执行。
	 */
	//应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		
	}

	/**
	 * 3、handler执行完成后执行此方法
	 */
	//应用场景:统一异常处理,统一日志处理
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		
	}

}

9.2、拦截器配置springmvc.xml

方式一:针对HandlerMapping进行拦截设置

springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的handler最终使用该拦截器。一般不推荐使用。

<bean
	class="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中。

	
	<mvc:interceptors>
		
		<mvc:interceptor>
			
			<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方法之前执行
	 */
	//应用场景:用于身份认证、身份授权
	//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行
	@Override
	public 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出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("HandlerInterceptor1...postHandle");
	}

	/**
	 * handler执行完成后执行此方法
	 */
	//应用场景:统一异常处理,统一日志处理
	@Override
	public 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方法之前执行
	 */
	//应用场景:用于身份认证、身份授权
	//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行
	@Override
	public 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出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("HandlerInterceptor2...postHandle");
	}

	/**
	 * handler执行完成后执行此方法
	 */
	//应用场景:统一异常处理,统一日志处理
	@Override
	public 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"%>




系统登陆



用户账号:
用户密码 :

登录的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){
		//清除session
		session.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{

	/**
	 * 用户身份验证
	 */
	//应用场景:用于身份认证、身份授权
	//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行
	@Override
	public 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出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("HandlerInterceptor2...postHandle");
	}

	/**
	 * handler执行完成后执行此方法
	 */
	//应用场景:统一异常处理,统一日志处理
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("HandlerInterceptor2...afterCompletion");
	}
}

拦截器配置:springmvc.xml

	
	<mvc:interceptors>
		
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.zwd.ssm.interceptor.LoginInterceptor">bean>
		mvc:interceptor>
		
		<mvc:interceptor>
			
			<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)