点击修改后进入修改页面
开发mapper
根据id查询商品信息
根据id更新items表的数据(数据库)
可以直接使用逆向工程的代码
开发service
根据id查询商品信息
修改商品信息(业务层)
ItemsService.java
public interface ItemsService {
//商品查询列表
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo)throws Exception;
//根据id查询商品信息
public ItemsCustom findItemsById(Integer id)throws Exception;
//修改商品信息。 id为修改商品的id,itemsCustom为修改的商品信息
public void updateItems(Integer id,ItemsCustom itemsCustom)throws Exception;
}
ItemsServiceImpl.java
public class ItemsServiceImpl implements ItemsService {
@Autowired
private ItemsMapperCustom itemsMapperCustom;
@Autowired
private ItemsMapper itemsMapper;
//itemsMapperCustom直接从service传到dao
@Override
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
// TODO Auto-generated method stub
return itemsMapperCustom.findItemsList(itemsQueryVo);
}
@Override
public ItemsCustom findItemsById(Integer id) throws Exception {
Items items = itemsMapper.selectByPrimaryKey(id);
//中间对商品信息进行业务处理
//...
//最后返回ItemsCustom
ItemsCustom itemsCustom = new ItemsCustom();
//将items的内容拷贝到itemsCustom
BeanUtils.copyProperties(items, itemsCustom);
return itemsCustom;
}
@Override
public void updateItems(Integer id, ItemsCustom itemsCustom) throws Exception {
//添加业务校验,在service接口对关键参数进行校验
//校验id是否为空,如果为空抛出spring的异常
//更新商品信息使用updateByPrimaryKeyWithBLOBs根据id更新items表中所有字段,包括大文本
//要求必须传入id,需要重复设置id
itemsCustom.setId(id);
itemsMapper.updateByPrimaryKeyWithBLOBs(itemsCustom);
}
}
============================================================================================
开发controller并调试
ItemsController.java
//使用Controller标识他是一个控制器
@Controller
public class ItemsController {
//注入service
@Autowired
private ItemsService itemsService;
//商品查询列表
//一般建议将url和方法名写成一样,方便queryItems和url进行映射,一个方法对应一个url
@RequestMapping("/queryItems")
public ModelAndView queryItems()throws Exception{
//调用service查找数据库,查询商品,这里先使用静态模拟
List<ItemsCustom> itemsList = itemsService.findItemsList(null);
//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList",itemsList);
//指定视图
//下边的路径,如果在视图解析器中配置jsp路径的前缀和jsp路径的后缀,就改为
//modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
//上边的路径配置可以不再程序中指定jsp路径的前缀和jsp路径的后缀
modelAndView.setViewName("items/itemsList");
return modelAndView;
}
//定义其他方法
//商品添加
//商品修改
//商品信息修改页面显示
@RequestMapping("/editItems")
public ModelAndView editItems()throws Exception{
//调用service根据商品id查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(1);
//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsCustom",itemsCustom);
//指定视图
modelAndView.setViewName("items/editItems");
return modelAndView;
}
//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public ModelAndView editItemsSubmit()throws Exception{
//调用service更新商品信息,页面需要将商品信息传到此方法
//.............
//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相当于request的setAttribut,在jsp页面中通过itemsList取数据
//modelAndView.addObject("itemsCustom",itemsCustom);
//指定视图
modelAndView.setViewName("success");
return modelAndView;
}
========================================================================================
调试:
itemsList.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>check list</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action="${pageContext.request.contextPath }/item/queryItem.action" method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询" /></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime }" pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/editItems.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
editItems.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>check list</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form id="itemForm" action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="id" value="${itemsCustom.id }" />
修改商品信息:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td><input type="text" name="name" value="${itemsCustom.name }" /></td>
</tr>
<tr>
<td>商品价格</td>
<td><input type="text" name="price" value="${itemsCustom.price }" /></td>
</tr>
<tr>
<td>商品的生产日期</td>
<td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime }" pattern="yyy-mm-dd HH:mm:ss" /> "/></td>
<tr>
<td>商品图片</td>
<td>
<c:if test="${itemsCustom.pic !=null }">
<img alt="" src="/pic/${itemsCustom.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>
===============================================================================================
controller注解开发
@requestMapping
定义controller方法对应的url,进行处理器映射。
1.窄化请求映射
ItemsController.java
@Controller
//为了对url进行分类管理可以定义一个根路径,最终访问url是根路径+子路径
//比如:商品列表:/items/queryItems.action
@RequestMapping("/items")
public class ItemsController {
还需要修改前台页面
itemsList.jsp
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime }" pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
还需要修改前台页面
editItems.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>check list</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post">
<input type="hidden" name="id" value="${itemsCustom.id }" />
2.限制http请求方法
处于安全考虑,如果限制请求为post方法,进行get请求,报错。
//商品信息修改页面显示
//@RequestMapping("/editItems")
//限制http请求方法 可以post和get
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView editItems()throws Exception{
===========================================================================================
controller方法的返回值
1.返回ModeAndView
2.返回string
返回string就是返回逻辑视图名。真正的视图(jsp路径)=前缀 +逻辑视图名 +后缀
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model)throws Exception{
//调用service根据商品id查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(1);
model.addAttribute("itemsCustom",itemsCustom);
return "items/editItems";
}
返回redirect
重定向特点:浏览器地址栏中的url会变化,修改提交的request数据无法传到重定向的地址。重定向后重新request(request无法共享)
//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit()throws Exception{
//重定向到商品列表
return "redirect:queryItems.action";
}
返回forward
通过forward页面转发:浏览器地址栏中的url会不变化,request可以共享
//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit()throws Exception{
//页面转发
return "forward:queryItems.action";
}
3.返回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串");
========================================================================================
参数绑定
从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。
在springmvc中,接收页面提交的数据是通过方法形参来接收,而不是在controller类定义成员变量来接收。
参数绑定默认支持
1.HttpServletRequest
2.HttpServletResponse
3.HttpSession
4.Model/ModelMap
5.还有简单类型
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model,Integer id)throws Exception{
//如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可以绑定成功。
//调用service根据商品id查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(id);
通过@RequestParam对简单类型的参数进行绑定。如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可以绑定成功。
如果使用注解不用限制request传入参数名称和controller方法的形参名称一致。
/@RequestParam里面指定request传入参数名称和形参进行绑定
//通过required属性指定参数是否必须要传入
//通过defaultValue可以设置默认值,如果id参数没有传入,可以将默认值和形参进行绑定
public String editItems(Model model,@RequestParam(value="id",required=true,defaultValue="")Integer items_id)throws Exception{
======================================================================================================================
7.绑定pojo
ItemsController.java
//商品信息修改提交
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(HttpServletRequest request,Integer id,ItemsCustom itemsCustom)throws Exception{
//调用service更新商品信息,页面需要将商品信息传到此方法
//.............
itemsService.updateItems(id, itemsCustom);
有值但是乱码
在web.xml中添加post乱码过滤器
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
对于get请求中文参数出现乱码解决方法有两个:
修改Tomcat配置文件添加编码与工程编码一致,如下
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPot="8443" />
另一种方法对参数进行重新编码:
String userName new
String(request.getParamter("userName").getBaytes("ISO8859-1"),"utf-8")
ISO8859-1是Tomcat默认编码,改变Tomcat编码后的内容按utf-8。
页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。
所以页面中的name的属性名很重要,只要一致就能绑定。
============================================================================================
8.自定义参数绑定实现日期类型绑定(未验证成功75、76日期参数绑定)
对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。
将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。
所以自定义参数绑定将日期串转成java.util.Date类型。
需要向处理器适配器中注入自定义的参数绑定组件。
<mvc:annotation-driven conversion-service="conversionService" />
打开商品生产日期选项
editItems.jsp
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post">
<input type="hidden" name="id" value="${itemsCustom.id }" />
修改商品信息:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td><input type="text" name="name" value="${itemsCustom.name }" /></td>
</tr>
<tr>
<td>商品价格</td>
<td><input type="text" name="price" value="${itemsCustom.price }" /></td>
</tr>
<tr>
<td>商品的生产日期</td>
<td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime }" pattern="yyy-mm-dd HH:mm:ss" /> "/></td>
</tr>
springmvc.xml
<!-- 注解映射器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />-->
<!-- 注解适配器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" /> -->
<!-- 使用mvc:annotation-driven 代替上边的注解映射器和注解适配器
mvc:annotation-driven默认加载很多的参数绑定方法,比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发使用的也是这个mvc:annotation-driven -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
springmvc.xml需要配置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>
创建controller.converter包
CustomDateConverter.java
import org.springframework.core.convert.converter.Converter;
public class CustomDateConverter implements Converter<String,Date> {@Override
public Date convert(String source) {
//将日期串转成日期类型
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
//转成直接返回
return simpleDateFormat.parse(source);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果参数绑定失败返回null
return null;
}
}
配置方式2比较繁琐
<!-- 注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
<!-- 自定义webBinder -->
<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
</bean>
<!-- conversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 转换器 -->
<property name="converters">
<list>
<bean class="cn.itcast.ssm.controller.converter.CustomDateConverter" />
<list>
</property>
</bean>
===========================================================================
SpringMVC和Struts区别
1.springmvc基于方法开发,struts基于类开发。
springmvc将url和controller方法映射,映射后springmvc生成一个Handller对象,对象只包括一个method。
方法执行结束,形参销毁。
所以springmvc可以进行单例,建议使用单例开发。就像数据库连接池就是单例模式,有且仅有一个连接池管理者,管理多个连接池对象。
之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;
之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;
用单例和多例的标准只有一个: 当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例
Struts2通过类开发,无法使用单例开发,只能用多例。
对于struts2来说,action必须用多例,因为action本身含有请求参数的值,即可改变的状态。
而对于struts1来说,action则可用单例,因为请求参数的值是放在actionForm中,而非action中的。
经过测试Struts慢,是因为使用Struts便签。