课程安排:
1、什么是springMVC?
2、springMVC框架原理
前端控制器、处理器映射器、处理器适配器、视图解析器。
3、springMVC入门程序
目的:对前端控制器、处理器映射器、处理器适配器、视图解析器
非注解的处理器映射器、处理器适配器
注解的处理器映射器、处理器适配器
4、springMVC和mybatis整合
5、springMVC注解开发
常用的注解学习
参数绑定(简单类型、pojo、集合类型)
自定义参数绑定
6、springMVC和struts2的区别
springMVC是spring框架的一个模块,springMVC和spring无需通过中间整合层进行整合。
springMVC是一个基于MVC的web框架。
MVC是一个设计模式,MVC在b/s系统下的应用:
第一步:发起请求到 前端控制器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……)
数据库环境:
/*
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.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>
在类路径下的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。
编写一个实现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;
}
}
<%@ 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"%>
查询商品列表
在类路径下的springmvc.xml
中配置:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">bean>
<bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1">bean>
在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>
http://localhost:8080/01.springmvcFirst/queryItems.action
BeanNameUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> bean>
<bean name="/queryItems.action" class="com.zwd.ssm.controller.ItemsController1"> bean>
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使用的处理器映射器,能使用哪个就使用哪个。
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;
}
}
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串");
}
}
前端控制器从上边的文件中加载处理器映射器、适配器、视图解析器等组件,如果不在springmvc.xml
中配置,则使用默认加载的。
3.1之前使用:
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
3.1之后使用:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
3.1之前使用:
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
3.1之后使用:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
记得添加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>
@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串");
}
//其它方法
}
<context:component-scan base-package="com.zwd.ssm.controller">context:component-scan>
http://localhost:8080/03.HandlerMappingAndAdapter_anno/queryItems.action
分析springmvc的执行过程。
第一步:前端控制器接受请求
调用doDispatch()
第二步:前端控制器调用处理器映射器。根据url查找handler
第三步:根据handler查找对应的处理器适配器,并调用该适配器执行该handler返回ModelAndView
第四步:视图渲染。将model数据填充到request域。
视图解析得到view。
<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>
非注解的处理器映射器(两种):BeanNameUrlHandlerMapping
、SimpleUrlHandlerMapping
<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>
非注解的处理器适配器(两种):SimpleControllerHandlerAdapter
、HttpRequestHandlerAdapter
<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>
<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);
使用springMVC和mybatis完成商品列表的查询。
springmvc和mybatis的系统架构
第一步:整合dao层
mybatis和spring整合,通过spring管理mapper接口。
使用mapper的扫描器自动扫描mapper接口在spring中的注册。MapperScannerConfigurer
第二步:整合service层
通过spring管理service接口。
通过配置方式将service接口配置在spring配置文件中。
实现事务控制(xml配置)。
第三步:整合springmvc的模块,不需要整合。
创建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
创建sqlMapConfig.xml
文件:config->mybatis->sqlMapConfig.xml
<configuration>
<typeAliases>
<package name="com.zwd.ssm.po"/>
typeAliases>
configuration>
创建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>
针对综合查询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;
}
}
<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>
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;
}
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);
}
}
<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>
<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>
<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>
<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>
<%@ 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"%>
查询商品列表
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;
}
}
<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>
http://localhost:8080/04.ssm/queryItems.action
操作流程:
1、进入商品查询列表页面(jsp/items/itemsList.jsp
)
2、点击修改,进入商品修改页面(jsp/items/editItems.jsp
),页面中显示了要修改的商品(从数据库中查询)
要修改的商品从数据库中查询,根据商品id(主键)查询商品信息。
3、在商品修改页面,修改商品信息,修改后,点击提交。页面跳转到jsp/success.jsp
mapper:使用逆向工程中的方法。
1、根据id查询商品信息。selectByPrimaryKey()
2、根据id更新items表的数据。updateByPrimaryKeyWithBLOBs()
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);
}
}
方法:
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>
没有实现页面之间的数据传送。
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;
}
}
http://localhost:8080/05.updateItemsInfo/queryItems.action
定义controller方法对应的url,进行处理器映射使用。
需要在方法结束时定义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;
}
表示返回逻辑视图名:真正视图(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";
在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串");
客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。
springMVC中,接收页面提交的数据时通过方法形参来接收的。而不是在controller类中定义成员变量接收。
直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。
通过request对象获取请求信息。
通过response处理响应信息。
通过session对象得到session中存放的对象。
model是一个接口,modelMap是一个接口实现。
作用:将model数据填充到request域。
通过@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;
}
要求:页面中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中的属性名称:
对于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日期类型
@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;
}
}
<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>
<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>
在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乱码原因: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编码
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支持
拦截器
商品查询controller方法中实现商品查询条件传入。
HttpServletRequest
request参数,通过接受查询条件参数。页面参数:
商品名称: 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;
}
}
在商品展示页面(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"%>
查询商品列表
关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。
形参名称与标签的name值一致
controller方法定义:
页面定义:
通常在需要批量提交数据时,将提交的数据绑定到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集合来接收批量提交的数据。
页面定义:
也通过在包装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());
}
项目中,通常使用较多的是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。
服务端校验:
控制层controller:校验页面请求的参数的合法性。在服务端控制层controller校验,不区分客户端类型(浏览器,手机客户端,远程调用)
业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数。
持久层dao:一般是不校验的。
springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。
校验思路:
页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。
具体需求:商品修改,添加校验(校验商品名称长度,生产日期的非空校验),如果校验出错,在商品修改页面显示错误信息。
<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>
validator="validator"
<mvc:annotation-driven conversion-service="conversionService" validator="validator">mvc:annotation-driven>
<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>
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;
#配置错误提示信息
items.name.length.error=商品名称在1到30个字符之间
items.createtime.isNull=请输入商品的日期
**捕获校验信息:**在需要校验的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";
}
将错误信息传到页面:
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>
在pojo中定义校验规则,而pojo是被多个controller所共用,当不同的controller方法对同一个pojo进行校验。但是每个controller方法需要不同的校验。
解决方法:
定义多个校验分组(其实是一个java接口),分组中定义有哪些规则。
每个controller方法使用不同的校验分组。
package com.zwd.ssm.controller.validation;
/**
* 校验分组
* @author Administrator
*
*/
public interface ValidGroup1 {
//此接口中不需要定义任何方法,仅是对不同的校验规则进行分组
//此分组校验商品名称长度
}
@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=) 被注释的元素必须在合适的范围内
提交后,如果出现错误,将刚才提交的数据回显到刚才的提交的页面。
@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>
对于简单数据类型,如: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);
系统中异常包括两类,预期异常和运行异常RunTimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springMVC前端控制器交给异常处理器进行异常处理。如下图:
springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
对不同的异常类型定义异常类,继承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;
}
}
思路:
系统遇到异常,在程序中手动抛出,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;
}
}
error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
错误页面
错误页面
<bean class="com.zwd.ssm.exception.CustomExceptionResolver">bean>
在controller、service、dao中任意一处需要手动抛出自定义异常。如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。
在商品修改的controller方法中抛出异常 :
在service中抛出异常:
如果与业务功能相关的异常,建议在service中抛出异常。
与业务功能没有关系的异常,建议在controller中抛出。
上边的功能,建议在service中抛出异常。
在修改商品页面,添加上传商品图片功能。enctype="multipart/form-data"
在页面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>
在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性能),一般我们采用按日期(年、月、日)进行分级创建。
商品图片
<%@ 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>
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";
}
json数据格式在接口调用中、HTML页面中较常用,json格式比较简单,解析还比较方便。
比如:webService接口,传输json数据。
1、请求json、输出json,要求请求的是json串,所以在前端页面中需要将请求的内容转成json,不太方便。
2、请求key/value、输出json。此方法比较常用。
作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。
作用:
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
springmvc中使用jackson的包进行json转换(@RequestBody、@ResponseBody使用下边的包进行json转换)
上述包不适用,已更换为下面三个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>
使用jQuery的ajax提交json串,对输出的json结构进行解析。
jsp页面代码
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
json交互测试
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
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
json交互测试
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包。
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。。
查询商品信息,返回json数据。
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;
// }
}
因为之前把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
继承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 {
}
}
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>
测试多个拦截器各各方法执行时机。
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方式二。
HandlerInterceptor1…preHandle
HandlerInterceptor2…preHandle
HandlerInterceptor2…postHandle
HandlerInterceptor1…postHandle
HandlerInterceptor2…afterCompletion
HandlerInterceptor1…afterCompletion
总结:
preHandle方法按顺序执行
postHandle和afterCompletion按拦截器配置的逆向顺序执行。
HandlerInterceptor1…preHandle
HandlerInterceptor2…preHandle
HandlerInterceptor1…afterCompletion
总结:
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle都不会执行。
HandlerInterceptor1…preHandle
HandlerInterceptor1…preHandle
总结:
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。
根据测试结果,对拦截器应用进行总结。
比如:统一日志处理拦截器,需要该拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)
1、用户请求url
2、拦截器进行拦截校验
如果请求的url是公开地址(无需登录即可访问的url),让放行
如果用户session不存在跳转到登录页面
如果用户session存在放行,继续操作
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
系统登陆
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");
}
}
<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