SpringMVC(二)

一、高级参数绑定

1.1 数组类型的参数绑定

基于批量删除商品操作完成参数传递。

jsp修改:

添加可选框,并设置name为ids,值为${item.id}
在这里插入图片描述

控制器修改

	@RequestMapping("queryItem")
	public String queryItem(QueryVo vo,Model model){
		if(vo.getItem()!=null){
			System.out.println(vo.getItem());
		}
		if(ids !=null &&ids.length>0){
			for(Integer id:ids){
				System.out.println(id);
			}
		}
		return "itemList";
	}

总结:在页面选中1、2商品时,并提交请求,会在控制台打印1、2,然后进行下一项尝试。

在这里插入图片描述

POJO修改

在这里插入图片描述

控制器修改

	@RequestMapping("queryItem")
	public String queryItem(QueryVo vo,Integer[] ids,Model model){
		if(vo.getIds() !=null &&vo.getIds().length>0){
			for(Integer id:vo.getIds()){
				System.out.println(id);
			}
		}
		if(ids !=null &&ids.length>0){
			for(Integer id:ids){
				System.out.println(id);
			}
		}
		return "itemList";
	}
小结:同样的请求操作,在queryvo中ids数组和形式参数接收数组ids的打印值相同,这就说明的springmvc的一个功能,可以自动的将页面的属性与接收参数进行匹配。

1.2 集合类型的参数绑定

修改pojo

在这里插入图片描述

修改jsp

<script type="text/javascript"
	src="${pageContext.request.contextPath }/My97Date/WdatePicker.js"></script>

	<form action="${pageContext.request.contextPath }/queryItem.action"
		method="post">
		查询条件:
		<table width="100%" border=1>
			<tr>
				<td>商品名称:<input type="text" name="item.name" /></td>
				<td>商品价格:<input type="text" name="item.price" /></td>
			</tr>
			<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>
				<td>商品描述</td>
				<td>操作</td>
			</tr>
			<c:forEach items="${itemList }" var="item" varStatus="status">
				<tr>
					<td><input type="checkbox" name="ids" value="${item.id}" /></td>
					<td>
						 <input type="hidden" name="items[${ status.index}].id" 
								value="${item.id }" />
						 <input type="text" name="items[${ status.index}].name" 
								value="${item.name }" />
					</td>
					<td>
						  <input type="text" name="items[${ status.index}].price" 
						  		value="${item.price }" />
					</td>
					<td>
	<%--  <fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss" /> --%>
	<input readonly="readonly" type="text" name="items[${ status.index}].createtime"
		   value='<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>'
	       onclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss'})" />
					</td>
					<td>
						<c:if test="${item.pic !=null}">
							<img src="/pic/${item.pic}" width=100 height=100 />
							<input type="hidden" name="items[${ status.index}].pic"
								value="${item.pic }" />
							<br />
						</c:if>
					</td>
					<td>
						<input type="text" name="items[${ status.index}].detail"
							 value="${item.detail }" />
					</td>
					<td>
						<a href="${pageContext.request.contextPath }/itemEdit.action?
						id=${item.id}">修改</a>
					</td>
				</tr>
			</c:forEach>

		</table>
	</form>

添加My97Date日期控件
在这里插入图片描述
varStatus属性常用参数总结如下:
在这里插入图片描述

小结:这里还不足以实现批量修改的功能,因为可能会报一个日期错误(Http Status 400-)。解决办法:定义日期转换器并配置。

定义日期转换器:

package springmvc.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.core.convert.converter.Converter;

/**
 * 日期转换器
 * 
 * Converter<S,T>
 * S:Source 要转换的源类型
 * T:目标,要转换成的数据类型
 * @author Administrator
 *
 */
public class DateConvert implements Converter<String, Date>{

	@Override
	public Date convert(String source) {
		Date result=null;
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			result = sdf.parse(source);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}
	
}

在springmvc.xml中配置日期转换器

	<!-- 配置注解驱动,相当于同时使用最新处理器映射跟处理器适配器,对json数据响应提供支持 -->
	<!--使用自定义转换器 -->
	<mvc:annotation-driven conversion-service="Myconvert" />
	
	<!--定义转换器 -->
	<bean id="Myconvert"
		class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
		<property name="converters">
			<set>
				<bean class="springmvc.utils.DateConvert" />
			</set>
		</property>
	</bean>

二、@RequestMapping注解的使用

2.1 路径映射可以是数组

在这里插入图片描述

2.2 @RequestMapping可以加在类头部,用于目录分级管理

在这里插入图片描述

2.3 限定请求方法

在这里插入图片描述

注意:当设置为get方式提交的时候,会出现乱码问题,解决办法:在tomcat的server.xml中,设置8080端口的地方增加:URIEncoding=“utf-8”
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" 
									protocol="HTTP/1.1" redirectPort="8443"/>

三、Controller方法返回值

3.1 返回ModelAndView

参考第一天内容

3.2 返回void

3.2.1 request

	@RequestMapping("queryVoid")
	public void queryVoid(HttpServletRequest request,HttpServletResponse response)
					 throws Exception{
		//request响应客户请求
		request.setAttribute("msg", "这个是request响应的消息");
		request.getRequestDispatcher("/jsp/msg.jsp").forward(request, response);
}

3.2.2 response

	@RequestMapping("queryVoid")
	public void queryVoid(HttpServletRequest request,HttpServletResponse response)
				 throws Exception{
		//response响应用户请求
		response.sendRedirect("/itemList.action");
}

3.2.3 设置响应字符的编码

	@RequestMapping("queryVoid")
	public void queryVoid(HttpServletRequest request,HttpServletResponse response)
			 throws Exception{
		//设置响应字符的编码(依然出现乱码:解决办法,将设置编码放到writer前面)
		response.setContentType("text/html; charset=UTF-8");
//		response.setCharacterEncoding("utf-8");
		PrintWriter printWriter=response.getWriter();
		printWriter.println("这个是response打印的消息");
	}

3.3 返回String

3.3.1 返回视图名字,参考第一次笔记

3.3.2 redirect与forward

在这里插入图片描述

注:使用转发和重定向分别在页面中打印msg的值如何编写jsp语句
转发:
	model.addAttribute("msg", "修改商品信息成功");
	//跳转到商品列表页面
	return "forward:itemList.action";

jsp页面:

<span>${ msg }</span><!--转发  -->
重定向
		model.addAttribute("msg", "修改商品信息成功");
		//跳转到商品列表页面
		return "redirect:itemList.action";

使用重定向的时候msg信息存放在url中
在这里插入图片描述
jsp页面:

<span>${ param.msg }</span><!--重定向  -->

四、Springmvc中异常处理

思想:做一个全局异常处理器,处理所有没有处理过的运行时异常用于更友好地提示用户。

4.1 步骤

4.1.1 创建全局异常处理器

/**
 * 全局异常处理器
 * @author Steven
 *
 */
public class CustomerException implements HandlerExceptionResolver {
	@Override
	public ModelAndView resolveException(HttpServletRequest request,
		 HttpServletResponse response, Object hanlder,
			Exception e) {
		//记录日志
		e.printStackTrace();
		//错误消息 
		String msg = "很抱歉,系统发生异常了,请联系管理员";
		
		//响应用户错误提示
		ModelAndView mav = new ModelAndView();
		//返回错误消息
		mav.addObject("msg", msg);
		//响应错误提示页面
		mav.setViewName("msg");
		return mav;
	}
}

4.1.2 配置异常处理器

	<!--配置全局异常处理器 -->
	 <bean class="springmvc.utils.CustomerException" /> 

4.1.3 测试访问queryVoid.action

在这里插入图片描述

4.1.4 更智能、更友好的提示,解决方案

4.1.4.1 新建自定义异常类
/**
 * 自定义异常
 * @author Steven
 *
 */
public class MyException extends Exception {
	
	//错误消息
	private String msg;

	public MyException() {
		super();
	}
	public MyException(String msg) {
		super();
		this.msg = msg;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
}
4.1.4.2 修改异常处理器,加上异常判断
package springmvc.exception;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

/**
 * 全局异常处理器
 * 
 * @author Administrator
 *
 */
public class CustomerException implements HandlerExceptionResolver {
	@Override
	public ModelAndView resolveException(HttpServletRequest request,
					 HttpServletResponse response, Object handler,Exception ex) {
		String msg="系统发生异常,请联系管理员";
		//自定义异常处理
		if(ex instanceof MyException){
			msg=((MyException)ex).getMsg();
		}
		ModelAndView mav = new ModelAndView();
		mav.addObject("msg",msg);
		mav.setViewName("msg");
		return mav;
	}
}
4.1.4.3 测试访问queryVoid.action
	/**
	 * 全局异常处理器+自定义异常处理
	 * @throws Exception 
	 */
	@RequestMapping("exceptionQuery")
	public void exceptionQuery() throws Exception{
		//假设这里是根据id查询商品信息,搜索不到商品
		if(true){
			throw new MyException("你查找的商品不存在,请确认信息");
		}
	}

五、图片上传处理

5.1 配置虚拟目录

在这里插入图片描述

5.2 加入上传功能需要的jar包

在这里插入图片描述

5.3 配置多媒体解析器

	<!-- 配置多媒体处理器 -->
	<!-- 注意:这里id必须填写:multipartResolver -->
	<bean id="multipartResolver" 
			class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 最大上传文件大小 -->
		<property name="maxUploadSize" value="8388608" />
	</bean>

5.4 itemEdit.jsp修改

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.5 编写图片上传处理代码

	/**
	 * 修改商品
	 * 
	 * 演示pojo参数绑定
	 * 
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping("updateItem")
	public String updateItem(Item item,MultipartFile pictureFile,Model model)
					 throws Exception{
		Item itemById = itemService.getItemById(item.getId());
	/*	System.out.println(itemById.getPic());
		System.out.println(item.getPic());*/
		if(!item.getPic().equals(itemById.getPic())){
		//图片新名字
		String newName =UUID.randomUUID().toString();
		//图片原来的名字
		String oldName = pictureFile.getOriginalFilename();
		//后缀
		String sux=oldName.substring(oldName.lastIndexOf("."));
		
		File file=new File("E:\\每日计划\\图片\\"+newName+sux);
		// 更新商品图片信息
		item.setPic(newName + sux);

		//写入本地磁盘
		pictureFile.transferTo(file);
		
	}
		itemService.updateItem(item);
		model.addAttribute("item", item);
		model.addAttribute("msg", "修改商品信息成功");
		return "itemEdit";
		//跳转到商品列表页面
	// return "forward:itemList.action";
	//	return "redirect:itemList.action";
	}

5.6 itemList.jsp修改

在这里插入图片描述

六、json数据交互

6.1 加入jar包

在这里插入图片描述

6.2 编码

	/**
	 * json数据交互演示
	 * 
	 * @param item2
	 * @return
	 */
	@RequestMapping("getItem")
	//@ResponseBody把pojo转成json串响应用户
	@ResponseBody
	public Item getItem() {
		Item item = itemServices.getItemById(1);
		return item;
	}

6.3 测试,安装google浏览器测试工具

打开网址:输入:chrome://apps
安装Advanced-REST-client_v3.1.9

将pojo转成json串

在这里插入图片描述

{
id: 1
name: "台式机"
price: 5000
detail: "性能好的不行"
pic: "6e6002d5-1634-4e3c-b23e-45a6efd5c66a.jpg"
createtime: 1559223587000
}

接收用户传入的json串转成pojo

	@RequestMapping("getItem")
	//@ResponseBody把pojo转成json串响应用户
	@ResponseBody
	//@RequestBody用于接收用户传入json串转成pojo
	public Item getItem(@RequestBody Item item2){
		System.out.println(item2);
		item2.setName("手机");
	//	Item item = itemService.getItemById(1);
		return item2;

输入json(注意格式)

在这里插入图片描述
接上
在这里插入图片描述

{
"id":1,
"name":"台式机",
"price":5000.0,
"detail":"性能好的不行",
"pic":"6e6002d5-1634-4e3c-b23e-45a6efd5c66a.jpg",
"createtime":1559223587000
}

输出

{
id: 1
name: "手机"
price: 5000
detail: "性能好的不行"
pic: "6e6002d5-1634-4e3c-b23e-45a6efd5c66a.jpg"
createtime: 1559223587000
}

七、Springmvc实现Restful

7.1 编码

	/**
	 * RESTful风格演示
	 * 
	 * @param ids
	 * @param model
	 * @return
	 */
	//RESTful风格url上的参数通过{}点位符绑定,因为id可变,所以用点位符
	//点位符参数名与方法参数名不一致时,通过@PathVariable绑定
	@RequestMapping("/item/{id}")
	public String testRest(@PathVariable Integer id, Model model) {
		Item item = itemService.getItemById(id);
		model.addAttribute("item", item);
		return "itemEdit";
	}

	/**
	 * 当接收的id与页面的id不一致时
	 */
	@RequestMapping("/item/{id}")
	public String testRest(@PathVariable("id") Integer ids, Model model) {
		Item item = itemService.getItemById(ids);
		model.addAttribute("item", item);
		return "itemEdit";
	}

7.2 测试

测试直接访问url{http://localhost:8080/项目名/item/1.action}即可。

八、拦截器

8.1 拦截器开发流程

8.1.1 创建拦截器

8.1.1.1 一号拦截器
package springmvc.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 定义拦截器
 * 
 * @author Administrator
 *
 */
public class MyInterceptor implements HandlerInterceptor {

	/*
	 * 多个拦截器拦截时,如果该拦截器放行,其他不放行,则会执行该拦截器的afterCompletion方法,
	 * 而其他拦截器则不执行
	 * 
	 * 因此,afterCompletion方法的执行与否是和拦截器是否放行一致,放行则执行,反之则不执行。
	 */
	// 方法执行之后被执行
	// 这里可以处理异常,清理资源,记录日志等等
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, 
				Object arg2, Exception arg3)throws Exception {
		System.out.println("MyInterceptor.afterCompletion.......");
	}

	// 方法执行之后,返回ModelAndView之前被执行
	// 设置页面的共用参数等等
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
	 			Object arg2, ModelAndView arg3)throws Exception {
		System.out.println("MyInterceptor.postHandle.......");
	}

	// 进入方法之前被执行
	// 这里可以用作:登录拦截,权限校验等等
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, 
				Object arg2)throws Exception {
		System.out.println("MyInterceptor.preHandle.......");
		// 返回true放行,false拦截
		return true;
	}

}
8.1.1.2 二号拦截器,复制一号,修改一下系统输出消息

8.1.2 配置拦截器

	<mvc:interceptors>
		<mvc:interceptor>
			<!--拦截所有请求,包括二级以上目录  -->
			<mvc:mapping path="/**"/>
			<bean class="springmvc.interceptor.MyInterceptor" />
		</mvc:interceptor>
		<mvc:interceptor>
		<!--"/**"表示:拦截所有请求,包括二级以上目录-->
		<mvc:mapping path="/**"/>
			<bean class="springmvc.interceptor.MyInterceptor2" />
		</mvc:interceptor>
	</mvc:interceptors>

8.1.3 输出

在这里插入图片描述

总结:

在这里插入图片描述

8.2 拦截器案例应用,登录拦截器

8.2.1 思路

1、有一个登录页面,需要写一个controller访问页面
2、登录页面有一提交表单的动作。需要在controller中处理。

  • a) 判断用户名密码是否正确
  • b) 如果正确 想session中写入用户信息
  • c) 返回登录成功,或者跳转到商品列表

3、拦截器。

  • a) 拦截用户请求,判断用户是否登录
  • b) 如果用户已经登录。放行
  • c) 如果用户未登录,跳转到登录页面。

8.2.2 login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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 }/user/login.action">
用户名:<input type="text" name="username" /><br>
密码:<input type="password" name="password" /><br>
<input type="submit">
</form>
</body>
</html>

8.2.3 UserController

package springmvc.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 用户请求处理器
 * 
 * @author Administrator
 *
 */
@Controller
@RequestMapping("user")
public class UserController {

	@RequestMapping("toLogin")
	public String toLogin() {
		return "login";
	}
	
	@RequestMapping("login")
	public String login(String username, String password, HttpSession session) {
		if (username.equals("admin")) {
			session.setAttribute("username", username);
			//注意:加个/,因为itmeList.action不在user目录下
			return "redirect:/itemList.action";
		} else
			return "login";
	}
}

8.2.4 LoginInterceptor拦截器编码

package springmvc.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 定义拦截器
 * 
 * @author Administrator
 *
 */
public class LoginInterceptor implements HandlerInterceptor {

	// 方法执行之后被执行
	// 这里可以处理异常,清理资源,记录日志等等
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1,
	 Object arg2, Exception arg3)
			throws Exception {
	}

	// 方法执行之后,返回ModelAndView之前被执行
	// 设置页面的共用参数等等
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, 
	Object arg2, ModelAndView arg3)
			throws Exception {
	}

	// 进入方法之前被执行
	// 这里可以用作:登录拦截,权限校验等等
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
	 Object arg2) throws Exception {
		// 判断用户有没有登录
		Object object =  request.getSession().getAttribute("username");
		if(object==null){
			//System.out.println(object.toString());
			System.out.println(request.getContextPath());
			response.sendRedirect(request.getContextPath()+"/user/toLogin.action");
		}
		// 返回true放行,false拦截
		return true;
	}

}

8.2.5 拦截器配置

		<mvc:interceptor>
			<!--"/**"表示:拦截所有请求,包括二级以上目录  -->
			<mvc:mapping path="/**"/>
			<!--配置不拦截目录  -->
			<mvc:exclude-mapping path="/user/**"/>
			<bean class="springmvc.interceptor.LoginInterceptor" />
		</mvc:interceptor>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值