springmvc概述(3)(映射注解,处理器返回类型,参数绑定,乱码,和struts区别)

1       商品修改功能开发

1.1      需求

操作流程:

1、进入商品查询列表页面
2、点击修改,进入商品修改页面,页面中显示了要修改的商品(从数据库查询)
   要修改的商品从数据库查询,根据商品id(主键)查询商品信息
3、在商品修改页面,修改商品信息,修改后,点击提交

1.2     开发mapper

mapper:
         根据id查询商品信息
         根据id更新Items表的数据
(不用开发了,使用逆向工程生成的代码。)

1.3      开发service

接口功能:
         根据id查询商品信息
         修改商品信息

1.4      开发controller

方法:
         商品信息修改页面显示
         商品信息修改提交

2       @RequestMapping

 url映射

ps:注解标注在方法上,表示路径和该方法映射

定义controller方法对应的url,进行处理器映射使用。

 窄化请求映射

ps:注解标注在类上,表示在特定的某个路径下

 

限制http请求方法

出于安全性考虑,对http的链接进行方法限制。

如果限制请求为post方法,进行get请求,报错:

ps:可以设置一个,也可以同时设置2个请求类型如下:

3       controller方法的返回值

返回ModelAndView

需要方法结束时,定义ModelAndView,将model和view分别进行设置。

返回string

<%@ 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"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>修改商品信息</title>

</head>
<body> 

<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="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>
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"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</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 }/items/editItems.action?id=${item.id}">修改</a></td>

</tr>
</c:forEach>

</table>
</form>
</body>

</html>
itemsList.jsp

如果controller方法返回string,

1、表示返回逻辑视图名。

真正视图(jsp路径)=前缀+逻辑视图名+后缀

ps:特别注意参数Model,这里应该是回调(特别之处是,对象的数据是通过作为参数被设置的,但又不是通过返回值获取)

2、redirect重定向

商品修改提交后,重定向到商品查询列表。

redirect重定向特点:浏览器地址栏中的url会变化。修改提交的request数据无法传到重定向的地址。因为重定向后重新进行request(request无法共享)

 

3、forward页面转发

通过forward进行页面转发,浏览器地址栏url不变,request可以共享。

(ps:id是从前端页面传递过来的值,被自动封装在request中)

返回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串");

4      参数绑定

ps:参数绑定就是,获取请求对应的参数

4.1      spring参数绑定过程

从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。

springmvc中,接收页面提交的数据是通过方法形参来接收。而不是在controller类定义成员变量接收!!!!

1.
客户端请求
key/value
2. 处理器适配器调用springmvc提供参数绑定组件将key/value数据转成controller方法的形参 参数绑定组件:在spirngmvc早期版本使用PropertyEditor(只能将字符串传成java对象)
后期使用converter(进行任意类型的传换) spirngmvc提供了很多converter(转换器) 在特殊情况下需要自定义converter 对日期数据绑定需要自定义converter
3. controller方法(形参)

4.2     默认支持的类型

直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。
(因为在参数绑定过程中,如果遇到下边类型直接进行绑定。前端调度器已经创建这些对象会根据参数类型自动传入)

4.2.1 HttpServletRequest

通过request对象获取请求信息

4.2.2 HttpServletResponse

通过response处理响应信息

4.2.3 HttpSession

通过session对象得到session中存放的对象

4.2.4 Model/ModelMap

model是一个接口,modelMap是一个接口实现 。

作用:将model数据填充到request域

4.3      简单类型

通过@RequestParam对简单类型的参数进行绑定。
如果不使用@RequestParam,要求request传入参数名称controller方法的形参名称一致,方可绑定成功。
如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。

通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,报下边错误:

ps: 注解的value的值是指前端的参数名称

4.4      pojo绑定

页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。

页面定义:

 

controller的pojo形参的定义:

4.5      自定义参数绑定实现日期类型绑定

@Controller
//为了对url进行分类管理 ,可以在这里定义根路径,最终访问url是根路径+子路径
//比如:商品列表:/items/queryItems.action
@RequestMapping("/items")
public class ItemsController {

    @Autowired
    private ItemsService itemsService;

    // 商品查询
    @RequestMapping("/queryItems")
    public ModelAndView queryItems(HttpServletRequest request) throws Exception {
        //测试forward后request是否可以共享
        
        System.out.println(request.getParameter("id"));

        // 调用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")
    //限制http请求方法,可以post和get
//    @RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
//    public ModelAndView editItems()throws Exception {
//        
//        //调用service根据商品id查询商品信息
//        ItemsCustom itemsCustom = itemsService.findItemsById(1);
//        
//        // 返回ModelAndView
//        ModelAndView modelAndView = new ModelAndView();
//        
//        //将商品信息放到model
//        modelAndView.addObject("itemsCustom", itemsCustom);
//        
//        //商品修改页面
//        modelAndView.setViewName("items/editItems");
//        
//        return modelAndView;
//    }
    
    @RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
    //@RequestParam里边指定request传入参数名称和形参进行绑定。
    //通过required属性指定参数是否必须要传入
    //通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定。
    public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
        
        //调用service根据商品id查询商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
        
        //通过形参中的model将model数据传到页面
        //相当于modelAndView.addObject方法
        model.addAttribute("itemsCustom", itemsCustom);
        
        return "items/editItems";
    }
    
    //商品信息修改提交
    @RequestMapping("/editItemsSubmit")
    public String editItemsSubmit(HttpServletRequest request,Integer id,ItemsCustom itemsCustom)throws Exception {
        
        //调用service更新商品信息,页面需要将商品信息传到此方法
        itemsService.updateItems(id, itemsCustom);
        
        //重定向到商品查询列表
//        return "redirect:queryItems.action";
        //页面转发
        //return "forward:queryItems.action";
        return "success";
    }
}
ItemsController.java
ps:即将请求参数传入pojo类中自定义的类中(字符串转换成相应的类,需要自定义转换器)

对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。

将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。

所以自定义参数绑定将日期串转成java.util.Date类型。

需要向处理器适配器中注入自定义的参数绑定组件。

4.5.1     自定义日期类型绑定

 

4.5.2     配置方式(springmvc.xml)

处理器的映射器/适配器注解

 

bean注册

5     post乱码

在web.xml添加post乱码filter

在web.xml中加入:

<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>

以上可以解决post请求乱码问题。

对于get请求中文参数出现乱码解决方法有两个:

修改tomcat配置文件添加编码与工程编码一致,如下:

<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

另外一种方法对参数进行重新编码:

String userName new 
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码

6     springmvc和struts2的区别

1springmvc基于方法开发的struts2基于类开发的
springmvc将url和controller方法映射
映射成功后springmvc生成一个Handler对象对象中只包括了一个method。方法执行结束,形参数据销毁。
springmvc的controller开发类似service开发。 2springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。 3、经过实际测试,struts2速度慢,在于使用struts标签如果使用struts建议使用jstl

7   总结

springmvc框架:

DispatcherServlet前端控制器:接收request,进行response
HandlerMapping处理器映射器: 根据url查找Handler。(可以通过xml配置方式,注解方式)
HandlerAdapter处理器适配器: 根据特定规则去执行Handler,编写Handler时需要按照HandlerAdapter的要求去编写。
Handler处理器(后端控制器): 需要程序员去编写,常用注解开发方式。
  Handler处理器执行后结果是ModelAndView,具体开发时Handler返回方法值类型包括 :
ModelAndView、
String(逻辑视图名)、
void(通过在Handler形参中添加request和response,类似原始 servlet开发方式,注意:可以通过指定response响应的结果类型实现json数据输出)
View resolver视图解析器: 根据逻辑视图名生成真正的视图(在springmvc中使用View对象表示) View视图: jsp页面,仅是数据展示,没有业务逻辑。

注解开发:

         使用注解方式的处理器映射器和适配器:

<!--注解映射器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--注解适配器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

在实际开发,使用<mvc:annotation-driven>代替上边处理器映射器和适配器配置。

@controller注解必须要加,作用标识类是一个Handler处理器。
@requestMapping注解必须要加,作用: 1、对url和Handler的方法进行映射。 2、可以窄化请求映射,设置Handler的根路径,url就是根路径+子路径请求方式 3、可以限制http请求的方法 映射成功后,springmvc框架生成一个Handler对象,对象中只包括 一个映射成功的method。

注解开发中参数绑定:

将request请求过来的key/value的数据(理解一个串),通过转换(参数绑定的一部分),将key/value串转成形参,将转换后的结果传给形参(整个参数绑定过程)。
springmvc所支持参数绑定:
1、默认支持很多类型,HttpServletRequest、response、session、
   model/modelMap(将模型数据填充到request域)
2、支持简单数据类型,整型、字符串、日期。。
   只要保证request请求的参数名和形参名称一致,自动绑定成功
   如果request请求的参数名和形参名称不一致,可以使用@RequestParam(指定request请求的参数名),@RequestParam加在形参的前边。
3、支持pojo类型
   只要保证request请求的参数名称和pojo中的属性名一致,自动将request请求的参数设置到pojo的属性中。
        注意:形参中即有pojo类型又有简单类型,参数绑定互不影响。
        自定义参数绑定:
            日期类型绑定自定义:
                定义的Converter<源类型,目标类型>接口实现类,比如:
                Converter<String,Date>表示:将请求的日期数据串转成java中的日期类型。
                注意:要转换的目标类型一定和接收的pojo中的属性类型一致。
                将定义的Converter实现类注入到处理器适配器中。
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
<!-- 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和struts2区别:

springmvc面向方法开发的(更接近service接口的开发方式),struts2面向类开发。
springmvc可以单例开发,struts2只能是多例开发。

 

posted @ 2018-06-03 23:10  假程序猿  阅读(324)  评论(0)    收藏  举报