Spring MVC - 开发 Controller的特性与乱码问题

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


你可能感兴趣的:(返回值,spring,mvc,参数,乱码,特性)