拓展商品修改功能
操作流程:
1)进入商品查询列表页面
2)点击修改,进入修改页面,页面显示的当前商品数据,通过id从数据库查询。
3)在修改页面中填写数据,最后点击修改,提交。
根据操作流程抽取出各层的责任
1、开发mapper
1.1 根据id查询Items表上的一行数据
1.2 根据id更新Items表的数据
2、开发serivice
2.1 根据id查询商品
2.1 修改商品信息
3、开发controller
3.1 处理查询商品的请求和响应
3.2 处理更新商品的请求和响应
1、开发mapper
1.1 根据id查询Items表上的一行数据
逆向工程提供了方法
Items selectByPrimaryKey(Integer id);
1.2 根据id更新Items表的数据
2、开发serivice
- 根据id查询商品
- 修改商品信息
2.1 接口定义
/**
* service接口的定义
* 并不需要遵循mapper的规范,这里只管如何调用mapper
*/
public interface ItemsService {
// 商品查询
List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception;
//根据id查询商品,使用商品的拓展类,防止业务拓展
ItemsCustom findItemsById(int id) throws Exception;
/**
* 更新商品信息
* @param id 修改商品的id
* @param itemsCustom 修改的商品信息
* @throws Exception
*/
void updateItems(int id,ItemsCustom itemsCustom) throws Exception;
}
2.2 接口实现
package cn.iot.ssm.service;
import cn.iot.ssm.mapper.ItemsMapperCustom;
import cn.iot.ssm.pojo.Items;
import cn.iot.ssm.pojo.query.ItemsCustom;
import cn.iot.ssm.pojo.query.ItemsQueryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ItemsServiceImpl implements ItemsService{
// ItemsMapperCustom所在的包已经被spring容器加载了,因此直接注入
@Autowired
private ItemsMapperCustom itemsMapperCustom;
@Autowired
private cn.iot.ssm.mapper.ItemsMapper itemsMapper;
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
return itemsMapperCustom.findItemsList(itemsQueryVo);
}
public ItemsCustom findItemsById(int id) throws Exception {
Items items = itemsMapper.selectByPrimaryKey(id);
//这里能添加业务处理,例如商品是否过期,如果过期添加标志
//因此利用拓展类ItemsCustom
ItemsCustom itemsCustom = new ItemsCustom();
// 将items里面的属性拷贝到拓展类
BeanUtils.copyProperties(items,itemsCustom);
return itemsCustom;
}
public void updateItems(Integer id, ItemsCustom itemsCustom) throws Exception {
//业务校验,对关键的参数进行校验
if (id != null) {
//使用这个方法更新items表中的所有字段,包括大文本类型
itemsCustom.setId(id);
itemsMapper.updateByPrimaryKeySelective(itemsCustom);
}
}
}
3、开发controller
- 处理查询商品的请求和响应
- 处理更新商品的请求和响应
由于还没有学会前端数据发到后台,也就是参数绑定,因此controller暂时写成这样
//处理商品修改请求
@RequestMapping("/editItems.action")
public ModelAndView editItems() throws Exception{
//调用service查询商品信息,需要获取前台数据 id
ItemsCustom itemsCustom = itemsService.findItemsById(1);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsCustom", itemsCustom);
modelAndView.setViewName("/WEB-INF/jsp/items/editItems.jsp");
return modelAndView;
}
//处理商品信息提交请求
@RequestMapping("/editItemsSubmit.action")
public ModelAndView editItemsSubmit() throws Exception{
//调用service更新信息
//需要获取前台数据 包装成修改后的Items
ModelAndView modelAndView = new ModelAndView();
//暂时返回一个成功页面
modelAndView.setViewName("index.jsp");
return modelAndView;
}
3、controller方法的返回值
3.1 返回ModelAndView
要设置model和view
3.2 返回String
3.2.1 返回jsp
String代表view,也就是视图;那么model可以通过形参传入
//处理商品修改请求
@RequestMapping("/editItems.action")
public String editItems(Model model) throws Exception{
//调用service查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(1);
model.addAttribute("itemsCustom",itemsCustom);
return "/WEB-INF/jsp/items/editItems.jsp";
}
3.2.2 重定向
例如在商品修改提交后,重定向到商品查询列表。
redirect的特点是:地址栏的url会变化,但是request无法进行转递参数,因为request和之前的request不属于同一个,因此controller和下一个界面无法进行request传参
//处理商品信息提交请求
@RequestMapping("/editItemsSubmit.action")
public String editItemsSubmit() throws Exception{
//调用service更新信息
//重定向,而且不用加根路径
return "redirect:queryItems.action";
}
3.2.3 转发
forward:controller和下一个界面共享一个request。也就是说可以通过request传参
3.3 返回void
4、参数绑定
从客户端请求的key/value数据经过参数绑定,把key/value绑定到controller的形参中。目的是为了前端jsp的数据传递到controller
springmvc提供了很多converter(转换器)来将任意类型的数据转换成java对象,但是有些特殊情况需要自己定义,例如日期数据
4.1 默认支持的类型
在controller方法的形参,定义下面的类型。那么springmvc的适配器会把用户请求的参数,绑定到这些组件中。
- HttpServletRequest
- HttpServletResponse
- HttpSession
- Model/ModelMap:接口和实现类,定义哪个都行
4.2 简单类型(int double string boolean)
通过这个,上面controller中editItems.action的指定id问题就解决了。
//处理商品修改请求
@RequestMapping("/editItems.action")
// @RequestParam指定了request传入的参数名称(也就是jsp指定id="",绑定到Items_id变量上)
//required标明这个参数是必须传的
public String editItems(Model model, @RequestParam(value = "id",required = true,defaultValue = "") Integer items_id) throws Exception{
//调用service查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
model.addAttribute("itemsCustom",itemsCustom);
return "/WEB-INF/jsp/items/editItems.jsp";
}
4.3 pojo类型绑定
在jsp文件中,我们把参数的name定义成itemsCustom所包含的属性一一对应,那么在controller就可以通过ItemsCustom itemsCustom形参进行接受。
<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>
在controller遗留下的问题也迎刃而解
//处理商品信息提交请求
@RequestMapping("/editItemsSubmit.action")
public String editItemsSubmit(Integer id,ItemsCustom itemsCustom) throws Exception{
//调用service更新信息
itemsService.updateItems(id,itemsCustom);
//重定向,而且不用加根路径
return "redirect:queryItems.action";
// return "/WEB-INF/jsp/success.jsp";
}
4.4 自定义类型绑定
对于日期类型的数据,需要自定义
需要向处理器适配器中注入自定义参数绑定
添加conversion-service属性,然后生成一个bean,class指定我们自己编写的一个转换器
转换器
public class CustomDateConverter implements Converter<String,Date> {
public Date convert(String s) {
//将日期串转换成日期类型(yyy-MM-dd HH:mm:ss)
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return simpleDateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
5、总结
- @controller注释必须要加,作用是标识类是一个controller
- @requestMapping注解必须要加,作用:
1)对url和Handler的方法进行映射
2)窄化请求映射,设置Handler的根路径
3)现在http请求的方法
5、遇到的问题
5.1 post乱码
在web.xml添加post乱码filter
<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>