1.回顾
在上一篇中我们演示了一个例子,简单的查询所有客户信息,在这里我们总结如下:
1.1 整合dao层 , mybatis和Spring整合:通过spring管理mapper接口
使用mapper的扫描器自动扫描mapper接口在spring中进行注册;
1.2 整理service层 :通过spring管理servie接口
通过配置方式将service接口配置在spring配置文件中,实现事务控制;
1.3 整合SpringMvc
由于SpringMvc是Spring的模块,不需要整合;
2.特性1 : @RequestMapping
2.1 定义controller方法对于的URL
可以在Controller根路径定义,可以进行分类请求,即窄化请求映射;
例如: 访问地址 :http://localhost:8989/SpringMvcMybatis1Demo/clients/clientsList.action
@Controller
@RequestMapping("/clients")
public class FClientController {
@Autowired
private FClientService fcService;
@RequestMapping("/clientsList")
public ModelAndView clientsList() {
ModelAndView view = new ModelAndView();
List<FClient> list;
try {
list = fcService.findClientList();
view.addObject("clients", list);
view.setViewName("/clientindex.jsp");
} catch (Exception e) {
view.addObject("error", e.getMessage());
view.setViewName("/error.jsp");
}
return view;
}}
2.2 限制http请求方法
出于安全性考虑 ,设置请求方式;
@RequestMapping(value="/editClientIfo",method={RequestMethod.POST,RequestMethod.GET})
3.特性2 :Controller 方法的返回值
3.1 返回ModelAndView
需要在方法结束时,定义ModelAndView,将model和view分别进行设置
例如:
@RequestMapping("/clientsList")
public ModelAndView clientsList() {
ModelAndView view = new ModelAndView();
List<FClient> list;
try {
list = fcService.findClientList();
view.addObject("clients", list);
view.setViewName("/clientindex.jsp");
} catch (Exception e) {
view.addObject("error", e.getMessage());
view.setViewName("/error.jsp");
}
return view;
}
3.2 返回string
如果controller方法返回string ,
(1)表示返回逻辑视图名
真正视图(jsp路径)= 前缀+逻辑视图名+后缀;
例如:
@RequestMapping("testString")
public String testString(Model model) {
try {
FClientCustom custom = fcService.findClientById(1);
model.addAttribute("custom", custom);
} catch (Exception e) {
model.addAttribute("error", "出错了! " + e.getMessage());
}
return "/clientedit.jsp";
}
(2)redirect 重定向
特点:浏览器地址栏的url会变化,修改提交的request数据无法传到重定向的地址,因为重定向的地址后重新进行了request;
使用: return "redirect:clientsList.action"
例如:
@RequestMapping("testString")
public String testString(Model model) {
try {
FClientCustom custom = fcService.findClientById(1);
model.addAttribute("custom", custom);
} catch (Exception e) {
model.addAttribute("error", "出错了! " + e.getMessage());
}
return "redirect:clientedit.jsp";
}
(3)forward 页面转发
使用: return "forward:该handler下的某个action" ;
例如:
@RequestMapping("testString")
public String testString(Model model) {
try {
FClientCustom custom = fcService.findClientById(1);
model.addAttribute("custom", custom);
} catch (Exception e) {
model.addAttribute("error", "出错了! " + e.getMessage());
}
return "forward:clientedit.jsp";
}
3.3 返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果;
(1)使用request转向页面,如下:
request.gerResquestDispatcher(“页面路径”).forword(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字符串");
例如:
@RequestMapping("testRequest")
public void testRequest(HttpServletRequest request,HttpServletResponse response) {
try {
int id = Integer.valueOf(request.getParameter("id"));
FClientCustom custom = fcService.findClientById(id);
request.setAttribute("custom", custom);
request.getRequestDispatcher("/clientedit.jsp").forward(request, response);
} catch (Exception e) {
request.setAttribute("error","出错了 ! "+e.getMessage());
try {
request.getRequestDispatcher("/error.jsp").forward(request, response);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
4.特性3 : 参数绑定
从客户端请求的key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上,springmvc中,接受页面提交的数据是通过方法形参来接收的,而不是在controller类定义成员变接收;处理器适配器调用springmvc提供参数绑定组件将key/value数据转成controller方法的形参;
参数绑定组件:
早期:使用PropertyEditor,将字符串转成java对象;
后期:使用converter进行任意类型转换;
spring提供了很多converter转换器,在特殊情况下,我们需要自定义converter,比如日期的converter转换器;
4.1 默认支持类型
直接在controller方法形参上定义下边类型对象,就可以使用这些类型,直接绑定;
(1)HttpServletRequest : 通过request对象获取请求信息;
(2)HttpServletResponse : 通过response处理响应信息;
例如:
@RequestMapping("testRequest")
public void testRequest(HttpServletRequest request,HttpServletResponse response) {
try {
int id = Integer.valueOf(request.getParameter("id"));
FClientCustom custom = fcService.findClientById(id);
request.setAttribute("custom", custom);
request.getRequestDispatcher("/clientedit.jsp").forward(request, response);
} catch (Exception e) {
request.setAttribute("error","出错了 ! "+e.getMessage());
try {
request.getRequestDispatcher("/error.jsp").forward(request, response);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
(3)HttpSession :通过session对象得到session中存放的对象;
(4)Model/ModelMap :Model是一个接口,modelMap是一个接口实现,作用是将model数据填充到request域;
例如:
@RequestMapping("testString")
public String testString(Model model) {
try {
FClientCustom custom = fcService.findClientById(1);
model.addAttribute("custom", custom);
} catch (Exception e) {
model.addAttribute("error", "出错了! " + e.getMessage());
}
return "forward:clientedit.jsp";
}
4.2 简单类型
通过@RequestParam 对简单类型的参数进行绑定;如果不使用@RequestParam ,要求request传入的参数名称和controller方法的形参名称一致,方可绑定成功;如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致;
例如:
/**
* 设置 @ReqeustParam()
* @param t_id
* @return
*/
@RequestMapping(value = "/editClientIfoTwo", method = { RequestMethod.POST,
RequestMethod.GET })
public ModelAndView editClientIfoTwo(@RequestParam(value="id") Integer t_id) {
// 模拟固定的id值,修改id为1的客户信息
ModelAndView view = new ModelAndView();
try {
FClientCustom custom = fcService.findClientById(t_id);
view.addObject("custom", custom);
view.setViewName("/clientedit.jsp");
} catch (Exception e) {
view.addObject("error", e.getMessage());
view.setViewName("error.jsp");
}
return view;
}
设置required属性为true,则指定参数必须要传入;
设置defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定;
例如:
@RequestMapping(value = "/editClientIfoThree", method = { RequestMethod.POST,
RequestMethod.GET })
public ModelAndView editClientIfoThree(@RequestParam(value="id",required=true) Integer t_id) {
// 模拟固定的id值,修改id为1的客户信息
ModelAndView view = new ModelAndView();
try {
FClientCustom custom = fcService.findClientById(t_id);
view.addObject("custom", custom);
view.setViewName("/clientedit.jsp");
} catch (Exception e) {
view.addObject("error", e.getMessage());
view.setViewName("error.jsp");
}
return view;
}
简单类型还有:int , String , double ,boolean
4.3 pojo绑定
页面中input的name值和controller的pojo形参中的属性名称一致,将页面中的数据绑定到pojo中;
例如:
jsp中的表单中的input的name值和pojo的属性名一直:
<input type="text" name="client_certificate_no" value="${custom.client_certificate_no}">
pojo :
private String client_certificate_no;
4.4 自定义参数绑定
将请求的日期数据串转成日期类型,对于controller形参中的pojo对象,如果属性中有日期类型,需要自定义参数绑定,要转换的日期类型和pojo的日期类型保持一致;需要向处理器适配器中注入自定义参数绑定组件!
示例:
首先我们使用的SpringMvc加载驱动用的是注解驱动的方式实现 :
<mvc:annotation-driven ></mvc:annotation-driven>
如果出错的话,引入命名空间:
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
(1)第一步:自定义参数类型,实现Convertor接口
例如:日期格式转换,将view中的日期字符串转换成我们pojo中data属性的类型;
/**
* 自定义参数类型,实现Converter接口
* TODO : 将日期字符串转为java.util.date类型
* 作者:原明卓
* 时间:2016年1月6日 下午4:30:46
* 工程:SpringMvcMybatis1Demo
*/
public class FormatDateConverter implements Converter<String,Date>{
@Override
public Date convert(String source) {
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return format.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
(2)第二步 : 配置转换器 conversionService
使用的是 :org.springframework.format.support.FormattingConversionServiceFactoryBean ;
例如:
<!-- 自定义类型,转成器 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<!-- 在这里可以定义多个转换 -->
<bean class="cn.labelnet.ssm.controller.converter.FormatDateConverter"></bean>
</list>
</property>
</bean>
在注解驱动中添加 :
<!-- 配置自定义参数映射 -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
(3)第三步 :不是重点
日期格式为了规范化,我们在input表单中添加 pattern属性 :
<input type="text" name="born_date" value="<fmt:formatDate value="${custom.born_date}" pattern="yyyy-MM-dd HH:mm:ss" />">
当然,在jsp中,需要引入两个tablib :
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
5.配置代码
SpringMvc完整示例 :注解驱动方式加载
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 配置Handler:扫描的方式 -->
<context:component-scan base-package="cn.labelnet.ssm.controller"></context:component-scan>
<!-- 注解映射器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
注解适配器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
-->
<!-- 使用Mvc:annotation-driven代替上面的注解映射器和适配器
mvc:annotation-driver默认加载很多的参数绑定方法;
那样就不用配置上班的requestMappingHandlerMapping和RequestMappingHandlerAdapter了
推荐使用;<mvc:annotation-driven></mvc:annotation-driven>
-->
<!-- 配置自定义参数映射 -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
<!-- 自定义类型,转成器 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<!-- 在这里可以定义多个转换 -->
<bean class="cn.labelnet.ssm.controller.converter.FormatDateConverter"></bean>
</list>
</property>
</bean>
</beans>
编辑页面 示例 :
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@ 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>
<base href="<%=basePath%>">
<title>My JSP 'clientedit.jsp' starting page</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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h1>修改客户信息</h1>
<form action="${pageContext.request.contextPath}/clients/editClientUpdate.action" method="post" style="width: 80%;">
<table align="center">
<tr>
<td>姓名 :</td>
<td>
<input type="hidden" name="id" value="${custom.id}">
<input type="text" name="username" value="${custom.username}"></td>
</tr>
<tr>
<td>客户代码 :</td>
<td><input type="text" name="client_certificate_no" value="${custom.client_certificate_no}"></td>
</tr>
<tr>
<td>生日 :</td>
<td><input type="text" name="born_date" value="<fmt:formatDate value="${custom.born_date}" pattern="yyyy-MM-dd HH:mm:ss" />"></td>
</tr> <tr>
<td>家庭住址:</td>
<td><input type="text" name="family_register_address" value="${custom.family_register_address}"></td>
</tr> <tr>
<td>现居住地 :</td>
<td><input type="text" name="now_address" value="${custom.now_address}"></td>
</tr> <tr>
<td>联系方式 :</td>
<td><input type="text" name="contact_mode" value="${custom.contact_mode}"></td>
</tr> <tr>
<td>紧急联系方式 :</td>
<td><input type="text" name="urgency_contact_mode" value="${custom.urgency_contact_mode}"></td>
</tr> <%-- <tr>
<td>注册日期 :</td>
<td><input type="text" readonly="readonly" name="create_date" value="${custom.create_date}"></td>
</tr> --%>
<tr>
<td>
<input type="submit" value="提交修改">
</td>
</tr>
</table>
</form>
</body>
</html>
6.乱码问题
6.1 post乱码
在web.xml中配置过滤器;
使用的是:org.springframework.web.filter.CharacterEncodingFilter
<!-- 过滤器 -->
<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>
6.2 Get乱码问题
(1) 修改tomcat配置文件添加编码与工程编码一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" ...../>
(2) 或者对参数进行重新编码:
String uname=new String(request.getParamter("uname").getBytes("ISO8859-1"),"UTF-8");
7.Spring Mvc 与 Strut2的区别
1) springmvc基于方法开发的,struct2基于类开发的
2) springmvc将url和controller方法映射,映射成功后将springmvc生成一个handler对象,对象中包括了一个method,方法执行结束,形参数据销毁;
3) springmvc可以进行单例开发,并且建议使用单例开发;
structs2通过类的成员变量接收参数,无法使用单例,只能使用多例;
4) springmvc的controller开发类似与service开发;
5) 经过实际测试,struts2速度慢,在于使用struts标签,建议使用jstl;
8.Demo免积分下载
http://download.csdn.net/detail/lablenet/9393772