内容简介:springmvc教程--注解开发基础详解
一、 注解开发 - 基础
1.1 需求
使用 springmvc+mybatis 架构 实现商品信息维护。
1.2 商品修改
1.2.1 dao
使用逆向工程自动生成的代码:
ItemsMapper. Java
ItemsMapper.xml
1.2.2 service
//根据id查询商品信息 public Items findItemById(int id) throws Exception; //修改商品信息 public void saveItem(Items items)throws Exception;
1.2.3 controller
修改商品信息显示页面:
@RequestMapping(value="/editItem") public String editItem(Model model, Integer id) throws Exception{ //调用service查询商品信息 Items item = itemService.findItemById(id); model.addAttribute("item", item); return "item/editItem"; }
修改商品信息提交:
//商品修改提交 @RequestMapping("/editItemSubmit") public String editItemSubmit(Items items)throws Exception{ System.out.println(items); itemService.saveItem(items); return "success"; }
1.2.4 页面
/WEB-INF/jsp/item/itemsList.jsp
/WEB-INF/jsp/item/editItem.jsp
1.3 @RequestMapping
通过 RequestMapping 注解可以定义不同的处理器映射规则。
1.3.1 URL 路径映射
@RequestMapping( value= "/item") 或 @RequestMapping("/item )
value 的值是数组,可以将多个 url 映射到同一个方法
1.3.2 窄化请求映射
在 class 上添加 @RequestMapping(url) 指定通用请求前缀, 限制此类下的所有方法请求 url 必须以请求前缀开头,通过此方法对 url 进行分类管理。
如下:
@RequestMapping 放在类名上边,设置请求前缀
@Controller
@ RequestMapping ("/item")
方法名上边设置请求映射 url :
@RequestMapping 放在方法名上边,如下:
@RequestMapping("/queryItem ")
访问地址为: /item/queryItem
1.3.3 请求方法限定
1、限定 GET 方法
@RequestMapping (method = RequestMethod. GET )
如果通过 Post 访问则报错:
HTTP Status 405 - Request method 'POST' not supported
例如:
@RequestMapping(value="/editItem",method=RequestMethod.GET)
2、 限定 POST 方法
@RequestMapping (method = RequestMethod. POST )
如果通过 Post 访问则报错:
HTTP Status 405 - Request method 'GET' not supported
3、GET 和 POST 都可以
@RequestMapping (method={RequestMethod.GET,RequestMethod.POST})
1.4 controller 方法返回值
1.4.1 返回 ModelAndView
controller 方法中定义 ModelAndView 对象并返回,对象中可添加 model 数据、指定 view 。
1.4.2 返回 void
在 controller 方法形参上可以定义 request 和 response ,使用 request 或 response 指定响应结果:
使用 request 转向页面,如下:
request.getRequestDispatcher(" 页面路径 ").forward(request, response);
通过 response 页面重定向:
response.sendRedirect("url")
通过 response 指定响应结果,例如响应 json 数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
1.4.3 返回字符串
1.4.3.1 逻辑视图名
controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/item/editItem.jsp return "item/editItem";
1.4.3.2 Redirect 重定向
Contrller 方法返回结果重定向到一个 url 地址,如下商品修改提交后重定向到商品查询方法,参数无法带到商品查询方法中。
//重定向到queryItem.action地址,request无法带过去 return "redirect:queryItem.action";
redirect 方式相当于“ response.sendRedirect() ”,转发后浏览器的地址栏变为转发后的地址,因为转发即执行了一个新的 request 和 response 。
由于新发起一个 request 原来的参数在转发时就不能传递到下一个 url ,如果要传参数可以 /item/queryItem.action 后边加参数,如下:
/item/queryItem?...&…..
1.4.3.3 forward 转发
controller 方法执行后继续执行另一个 controller 方法,如下商品修改提交后转向到商品修改页面,修改商品的 id 参数可以带到商品修改方法中。
//结果转发到editItem.action,request可以带过去 return "forward:editItem.action";
forward 方式相当于“ request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的 request 和 response ,而是和转发前的请求共用一个 request 和 response 。所以转发前请求的参数在转发后仍然可以读取到。
1.5 参数绑定
1.5.1 默认支持的参数类型
处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值。
1.5.1.1 HttpServletRequest
通过 request 对象获取请求信息
1.5.1.2 HttpServletResponse
通过 response 处理响应信息
1.5.1.3 HttpSession
通过 session 对象得到 session 中存放的对象
1.5.1.4 Model
通过 model 向页面传递数据,如下:
//调用service查询商品信息 Items item = itemService.findItemById(id); model.addAttribute("item", item);
页面通过 ${ item .XXXX} 获取 item 对象的属性值。
1.5.2 参数绑定介绍
注解适配器对 RequestMapping 标记的方法进行适配,对方法中的形参会进行参数绑定,早期 springmvc 采用 PropertyEditor (属性编辑器)进行参数绑定将 request 请求的参数绑定到方法形参上, 3.X 之后 springmvc 就开始使用 Converter 进行参数绑定。
1.5.3 @RequestParam
@RequestParam 用于绑定单个请求参数。
value : 参数名字,即入参的请求参数名字,如 value=“item_id” 表示请求的参数区中的名字为 item_id 的参数的值将传入;
required : 是否必须,默认是 true ,表示请求中一定要有相应的参数,否则将报;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue : 默认值,表示如果请求中没有同名参数时的默认值
定义如下:
public String editItem(@RequestParam(value="item_id",required=true) String id) { }
形参名称为 id ,但是这里使用 value=" item_id" 限定请求的参数名为 item_id ,所以页面传递参数的名必须为 item_id 。
注意:如果请求参数中没有 item_id 将跑出异常:
HTTP Status 500 - Required Integer parameter 'item_id' is not present
这里通过 required=true 限定 item_id 参数为必需传递,如果不传递则报 400 错误,可以使用 defaultvalue 设置默认值,即使 required=true 也可以不传 item_id 参数值
1.5.4 简单类型
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。
1.5.4.1 整型
public String editItem(Model model, Integer id ) throws Exception {
}
1.5.4.2 字符串
例子略
1.5.4.3 单精度 / 双精度
例子略
1.5.4.4 布尔型
处理器方法:
public String editItem(Model model,Integer id, Boolean status ) throws Exception
请求 url:
http://localhost:8080/springmvc_mybatis/item/editItem.action?id=2 &status=false
说明:对于布尔类型的参数,请求的参数值为 true 或 false 。
1.5.5 自定义参数绑定
1.5.5.1 需求
根据业务需求自定义日期格式进行参数绑定。
1.5.5.2 propertyEditor
1.5.5.2.1
使用 WebDataBinder
在 controller 方法中通过 @InitBinder 标识方法为参数绑定方法,通过 WebDataBinder 注册属性编辑器,问题是此方法只能在单个 controller 类中注册。
/** * 注册属性编辑器(字符串转换为日期) */ @InitBinder public void initBinder(WebDataBinder binder) throws Exception { binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); }
1.5.5.2.2 使用 WebDataBinder
在 controller 方法中通过 @InitBinder 标识方法为参数绑定方法,通过 WebDataBinder 注册属性编辑器,问题是此方法只能在单个 controller 类中注册。
如下:
编写 CustomPropertyEditor :
public class CustomPropertyEditor implements PropertyEditorRegistrar { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true)); } }
配置如下:
<!-- 注册属性编辑器 --> <bean id="customPropertyEditor" class="com.sihai.ssm.propertyeditor.CustomPropertyEditor"></bean> <!-- 自定义webBinder --> <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="propertyEditorRegistrars"> <list> <ref bean="customPropertyEditor"/> </list> </property> </bean> <!--注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="customBinder"></property> </bean>
1.5.5.3 Converter
1.5.5.3.1 自定义 Converter
public class CustomDateConverter implements Converter<String, Date> { @Override public Date convert(String source) { try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); return simpleDateFormat.parse(source); } catch (Exception e) { e.printStackTrace(); } return null; } }
1.5.5.3.2 配置方式 1
<!--注解适配器 --> <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>
1.5.5.3.3 配置方式 2
<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>
1.5.6 pojo
1.5.6.1 简单 pojo
将 pojo对象中的属性名于传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中
页面定义如下 ;
<input type="text" name=" name "/>
<input type="text" name=" price "/>
Contrller方法定义如下:
@RequestMapping("/editItemSubmit") public String editItemSubmit(Items items)throws Exception{ System.out.println(items);
请求的参数名称和 pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
1.5.6.2 包装 pojo
如果采用类似 struts中对象.属性的方式命名,需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。
包装对象定义如下:
Public class QueryVo { private Items items; }
页面定义:
<input type="text" name=" items. name " />
<input type="text" name=" items. price" />
Controller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{ System.out.println(queryVo.getItems());
1.5.6.3ModelAttribute
@ModelAttribute 作用如下:
1 、绑定请求参数到 pojo 并且暴露为模型数据传到视图页面
此方法可实现数据回显效果。
// 商品修改提交 @RequestMapping("/editItemSubmit") public String editItemSubmit(@ModelAttribute("item") Items items,Model model)
页面:
<tr> <td>商品名称</td> <td><input type="text" name="name" value="${item.name }"/></td> </tr> <tr> <td>商品价格</td> <td><input type="text" name="price" value="${item.price }"/></td> </tr>
如果不用 @ModelAttribute 可以使用 model.addAttribute("item", items) 完成数据回显。
2 、将方法返回值暴露为模型数据传到视图页面
//商品分类 @ModelAttribute("itemtypes") public Map<String, String> getItemTypes(){ Map<String, String> itemTypes = new HashMap<String,String>(); itemTypes.put("101", "数码"); itemTypes.put("102", "母婴"); return itemTypes; }
页面:
商品类型:
<select name="itemtype"> <c:forEach items="${itemtypes }" var="itemtype"> <option value="${itemtype.key }">${itemtype.value }</option> </c:forEach> </select>
1.5.7 集合类
1.5.7.1 字符串数组
页面定义如下:
页面选中多个 checkbox向controller方法传递
<input type="checkbox" name="item_id" value="001"/> <input type="checkbox" name="item_id" value="002"/> <input type="checkbox" name="item_id" value="002"/>
传递到 controller方法中的格式是:001,002,003
Controller方法中可以用String[]接收,定义如下:
public String deleteitem(String[] item_id)throws Exception{ System.out.println(item_id); }
1.5.7.2 List
List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。
List中对象:
成绩对象
Public class QueryVo { Private List<Items> itemList;//订单明细 //get/set方法.. }
包装类中定义 List对象,并添加get/set方法如下:
页面:
<tr> <td> <input type="text" name=" itemList[0].id" value="${item.id}"/> </td> <td> <input type="text" name=" itemList[0].name" value="${item.name }"/> </td> <td> <input type="text" name=" itemList[0].price" value="${item.price}"/> </td> </tr> <tr> <td> <input type="text" name=" itemList[1].id" value="${item.id}"/> </td> <td> <input type="text" name=" itemList[1].name" value="${item.name }"/> </td> <td> <input type="text" name=" itemList[1].price" value="${item.price}"/> </td> </tr>
Contrller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{ System.out.println(queryVo.getItemList()); }
1.5.7.3 Map
在包装类中定义 Map对象,并添加get/set方法,action使用包装对象接收。
包装类中定义 Map对象如下:
Public class QueryVo { private Map<String, Object> itemInfo = new HashMap<String, Object>(); //get/set方法.. }
页面定义如下:
<tr> <td>学生信息:</td> <td> 姓名:<inputtypeinputtype="text"name="itemInfo['name']"/> 年龄:<inputtypeinputtype="text"name="itemInfo['price']"/> .. .. .. </td> </tr>
Contrller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{ System.out.println(queryVo.getStudentinfo()); }
1.6 问题总结
1.6.1 404
页面找不到,视图找不到。
HandlerMapping 根据 url 没有找到 Handler 。
1.6.2 Post 时中文乱码
在 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 编码
1.7 与 struts2 不同
1、 springmvc 的入口是一个 servlet 即前端控制器,而 struts2 入口是一个 filter 过虑器。
2、springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
3、 Struts 采用值栈存储请求和响应的数据,通过 OGNL 存取数据, springmvc 通过参数解析器是将 request 请求内容解析,并给方法形参赋值,将数据和视图封装成 ModelAndView 对象,最后又将 ModelAndView 中的模型数据通过 reques 域传输到页面。 Jsp 视图解析器默认使用 jstl 。
动动小手关注我的微信公众号吧 好好学java
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Java注解Annotation与自定义注解详解
- Retrofit使用详解-注解介绍
- Spring IoC 公共注解详解
- spring mvc 常用注解详解
- 「Java笔记」 详解 Spring 注解 @Autowired
- Java中lombok @Builder注解使用详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective Modern C++
Scott Meyers / O'Reilly Media / 2014-12 / USD 49.99
Learn how to program expertly with C++ with this practical book from Scott Meyers, one of the world's foremost authorities on this systems programming language. Scott Meyers takes some of the most dif......一起来看看 《Effective Modern C++》 这本书的介绍吧!