【SpringMVC框架入门】02- 请求参数绑定,controller方法返回值,整体异常处理,图片上传(fileupload),Json数据交互,RestFul支持,拦截器,登录权限验证

总结:

☆1.参数绑定:(从请求中接收参数)

1)默认支持的类型:Request,Response,Session,Model
2)基本数据类型(包含String)
3)Pojo类型
4)Vo类型
5)Converter自定义转换器
6)数组
7)List

itemList.jsp

<form action="${pageContext.request.contextPath }/updateAll.action" method="post">
查询条件:
<table width="100%" border=1>
<tr>
<!-- 如果Controller中接收的是Vo,那么页面上input框的name属性值要等于vo的属性.属性.属性..... -->
<td>商品名称:<input type="text" name="items.name"/></td>
<td>商品价格:<input type="text" name="items.price"/></td>
<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>
</tr>
<c:forEach items="${itemList }" var="item" varStatus="status">
<tr>
	<!-- name属性名称要等于vo中的接收的属性名 -->
	<!-- 如果批量删除,可以用List<pojo>来接收,页面上input框的name属性值= vo中接收的集合属性名称+[list的下标]+.+list泛型的属性名称 -->
	<td>
		<input type="checkbox" name="ids" value="${item.id }"/>
		<input type="hidden" name="itemsList[${status.index }].id" value="${item.id }"/>
	</td>
	<td><input type="text" name="itemsList[${status.index }].name" value="${item.name }"/></td>
	<td><input type="text" name="itemsList[${status.index }].price" value="${item.price }"/></td>
	<td><input type="text" name="itemsList[${status.index }].createtime" 
			   value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
	<td><input type="text" name="itemsList[${status.index }].detail" value="${item.detail }"/></td>
	
	<td><a href="${pageContext.request.contextPath }/items/itemEdit/${item.id}">修改</a></td>

</tr>
</c:forEach>

</table>
</form>

varStatus属性常用参数总结下:

${status.index} 输出行号,从0开始。
${status.count} 输出行号,从1开始。
${status.current} 当前这次迭代的(集合中的)项
${status.first} 判断当前项是否为集合中的第一项,返回值为true或false
${status.last} 判断当前项是否为集合中的最后一项,返回值为true或false
begin、end、step分别表示:起始序号,结束序号,跳跃步伐。

QueryVo.java

public class QueryVo {
	//商品对象
	private Items items;
	//订单对象...
	//用户对象....

	//批量删除使用
	private Integer[] ids;
	//批量修改使用
	private List<Items> itemsList;

ItemsController.java QueryVo.getIds();

@RequestMapping("/updateAll")
	//public String updateAll(String[] ids) throws Exception{
	public String updateAll(QueryVo vo) throws Exception{
		System.out.println(vo.getIds());
		return "";
	}
@RequestMapping("/updateAll")
	public String updateAll(QueryVo vo) throws Exception{
		System.out.println(vo.getItemsList());
		return "";
	}

窄化请求映射

@Controller
//窄化请求映射:为防止你和你的队友在conroller方法起名的时候重名,所以相当于在url中多加了一层目录,防止重名
//例如:当前list的访问路径   localhost:8081/ssm0523-1/items/list.action
@RequestMapping("/items")
public class ItemsController {

	@Autowired
	private ItemsService itmesService;

请求方法限定

@RequestMapping(method = RequestMethod.GET)

@RequestMapping(method = RequestMethod.POST)

☆2.controller方法返回值(指定返回到哪个页面, 指定返回到页面的数据)

1)ModelAndView

	modelAndView.addObject("itemList", list); 指定返回页面的数据
	modelAndView.setViewName("itemList");	  指定返回的页面

2)String(推荐使用)

返回普通字符串,就是页面去掉扩展名的名称, 返回给页面数据通过Model来完成
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/item/editItem.jsp
return "item/editItem";
返回的字符串以forward:开头为请求转发
//结果转发到editItem.action,request可以带过去
//request.getRequestDispatcher().forward(request,response)
return "forward:editItem.action";
返回的字符串以redirect:开头为重定向
//重定向到queryItem.action地址,request无法带过去
//response.sendRedirect()
return "redirect:queryItem.action";

3)返回void(使用它破坏了springMvc的结构,所以不建议使用)

	可以使用request.setAttribut 来给页面返回数据
	可以使用request.getRquestDispatcher().forward()来指定返回的页面
	如果controller返回值为void则不走springMvc的组件,所以要写页面的完整路径名称

相对路径:相对于当前目录,也就是在当前类的目录下,这时候可以使用相对路径跳转

绝对路径:从项目名后开始.

在springMvc中不管是forward还是redirect后面凡是以/开头的为绝对路径,不以/开头的为相对路径
例如:forward:/items/itemEdit.action 为绝对路径
	forward:itemEdit.action为相对路径

3.架构级别异常处理:

主要为了防止项目上线后给用户抛500等异常信息,所以需要在架构级别上整体处理.hold住异常
首先自定义全局异常处理器实现HandlerExceptionResolver接口
在spirngMvc.xml中配置生效

系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
在这里插入图片描述

自定义异常 CustomException.java

//自定义异常类,用来处理自定义异常
public class CustomException extends Exception{
	//保存异常信息
	private String  message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

}

自定义异常处理器 CustomGlobalExceptionResolver.java

//自定义全局异常处理
public class CustomGlobalExceptionResolver implements HandlerExceptionResolver{

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, 
			Object arg2, Exception exc) {
		//保存异常信息
		String msg = "";
		
		//判断异常类型
		if(exc instanceof CustomException){
			//处理业务级别异常
			msg = ((CustomException)exc).getMessage();
		} else {
			//处理运行时异常
			msg = "系统异常, 亲,对不起, 请及时联系管理员哦!";
		}
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("msg", msg);
		modelAndView.setViewName("error");
		return modelAndView;
	}

}

错误页面 error.jsp

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body> 
${msg}
</body>

</html>

异常处理器配置SpringMvc.xml

<!-- 配置全局异常处理器 -->
	<bean class="cn.itheima.exception.CustomGlobalExceptionResolver"></bean>

异常测试

@RequestMapping("/list")
	public ModelAndView itemsList() throws Exception{
		//测试运行时异常
		//int i= 0/0;
		
		//测试自定义异常
//		if(true){
//			CustomException customException = new CustomException();
//			customException.setMessage("对不起哦, 您已经抢购过, 不要太贪心哦!");
//			throw customException;
//		}
		
		List<Items> list = itmesService.list();
		
		ModelAndView modelAndView = new ModelAndView();
		
		modelAndView.addObject("itemList", list);
		modelAndView.setViewName("itemList");
		
		return modelAndView;
	}

4.上传图片:

1)在tomcat中配置虚拟图片服务器.

在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:
<Context docBase="F:\develop\upload\temp" path="/pic" reloadable="false"/>

访问http://localhost:8080/pic即可访问F:\develop\upload\temp下的图片。

也可以通过eclipse配置:

在这里插入图片描述

2)导入fileupload的jar包

CommonsMultipartResolver
在这里插入图片描述

3)在springMvc.xml中配置上传组件

<!-- 文件上传 -->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置上传文件的最大尺寸为5MB -->
		<property name="maxUploadSize">
			<value>5242880</value>
		</property>
	</bean>

4)在页面上编写上传域,更改form标签的类型

<!-- 上传图片是需要指定属性 enctype="multipart/form-data" -->
	<form id="itemForm" action="${pageContext.request.contextPath }/items/updateitem" 
	method="post" enctype="multipart/form-data">
<%-- 	<form id="itemForm"	action="${pageContext.request.contextPath }/items/updateitem.action" method="post"> --%>
	<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>


5)在controller方法中可以使用MultiPartFile接口接收上传的图片

//spirngMvc可以直接接收pojo类型:要求页面上input框的name属性名称必须等于pojo的属性名称
	@RequestMapping("/updateitem")
	//public String update(Integer id, String name, Float price, String detail) throws Exception{
	public String update(MultipartFile pictureFile,Items items, Model model, HttpServletRequest request) throws Exception{
		//1. 获取图片完整名称
		String fileStr = pictureFile.getOriginalFilename();
		//2. 使用随机生成的字符串+源图片扩展名组成新的图片名称,防止图片重名
		String newfileName = UUID.randomUUID().toString() + fileStr.substring(fileStr.lastIndexOf("."));
		//3. 将图片保存到硬盘
		pictureFile.transferTo(new File("D:\\java\\pic\\" + newfileName));
		//4.将图片名称保存到数据库
		items.setPic(newfileName);
		itmesService.updateItems(items);
		//返回数据
		//request.setAttribute("", arg1);
		//指定返回的页面(如果controller方法返回值为void,则不走springMvc组件,所以要写页面的完整路径名称)
		//request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
		
		//重定向:浏览器中url发生改变,request域中的数据不可以带到重定向后的方法中
		//model.addAttribute("id", items.getId());
		//在springMvc中凡是以redirect:字符串开头的都为重定向
		return "redirect:itemEdit/"+items.getId();
		
		//请求转发:浏览器中url不发生改变,request域中的数据可以带到转发后的方法中
		//model.addAttribute("id", items.getId());
		//spirngMvc中请求转发:返回的字符串以forward:开头的都是请求转发, 
		//后面forward:itemEdit.action表示相对路径,相对路径就是相对于当前目录,当前为类上面指定的items目录.在当前目录下可以使用相对路径随意跳转到某个方法中
		//后面forward:/itemEdit.action路径中以斜杠开头的为绝对路径,绝对路径从项目名后面开始算
		//return "forward:/items/itemEdit.action";
	}

6)将文件名保存到数据库,将图片保存到磁盘中

5.Json数据交互:

需要加入jackson的jar包

在这里插入图片描述

配置json转换器

在注解适配器中加入messageConverters
<!--注解适配器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
		<list>
		<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
		</list>
		</property>
	</bean>

注意:如果使用<mvc:annotation-driven /> 则不用定义上边的内容。

@Requestbody:将页面传到controller中的json格式字符串自动转换成java的pojo对象

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

List.action?id=1&name=zhangsan&age=12

<script type="text/javascript">
	function sendJson(){
		//请求json响应json
		$.ajax({
			type:"post",
			url:"${pageContext.request.contextPath }/items/sendJson.action",
			contentType:"application/json;charset=utf-8",
			data:'{"name":"测试商品","price":99.9}',
			success:function(data){
				alert(data);
			}
		});
		
	}
</script>
//导入jackson的jar包在 controller的方法中可以使用@RequestBody,让spirngMvc将json格式字符串自动转换成java中的pojo
	//页面json的key要等于java中pojo的属性名称
	//controller方法返回pojo类型的对象并且用@ResponseBody注解,springMvc会自动将pojo对象转换成json格式字符串
	@RequestMapping("/sendJson")
	@ResponseBody
	public Items json(@RequestBody Items items) throws Exception{
		System.out.println(items);
		return items;
	}

@ResponseBody:将java中pojo对象自动转换成json格式字符串返回给页面

该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

测试结果

在这里插入图片描述

6.RestFul支持:

就是对url的命名标准,要求url中只有能名词,没有动词(不严格要求),但是要求url中不能用问号?传参
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格,是对http协议的诠释。
资源定位:互联网所有的事物都是资源,要求url中没有动词,只有名词。没有参数
Url格式:http://blog.csdn.net/beat_the_world/article/details/45621673
资源操作:使用put、delete、post、get,使用不同方法对资源进行操作。分别对应添加、删除、修改、查询。一般使用时还是post和get。Put和Delete几乎不使用。

添加DispatcherServlet的rest配置

<servlet-mapping>  
	    <servlet-name>default</servlet-name> 
	    <url-pattern>*.jpg</url-pattern>    
	</servlet-mapping>   
	<servlet-mapping>      
	    <servlet-name>default</servlet-name>   
	    <url-pattern>*.js</url-pattern>   
	</servlet-mapping>   
	<servlet-mapping>       
	    <servlet-name>default</servlet-name>      
	    <url-pattern>*.css</url-pattern>     
	</servlet-mapping>
	  
  <!-- springmvc前端控制器 -->
  <servlet>
  	<servlet-name>springMvc</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:SpringMvc.xml</param-value>
  	</init-param>
  	<!-- 在tomcat启动的时候就加载这个servlet -->
  	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>springMvc</servlet-name>
  	<!-- 
  	*.action    代表拦截后缀名为.action结尾的
  	/ 			拦截所有但是不包括.jsp
  	/* 			拦截所有包括.jsp
  	 -->
  	<url-pattern>/</url-pattern>
  </servlet-mapping>
传参数:
	页面:${pageContext.request.contextPath }/items/itemEdit/${item.id}
	方法: @RquestMapping("/itemEdit/{id}")
	方法: @PathVariable("id") Integer idd
/**
		 *
	 *通过@PathVariable可以接收url中传入的参数
	 *@RequestMapping("/itemEdit/{id}")中接收参数使用大括号中加上变量名称, @PathVariable中的变量名称要和RequestMapping
	 *中的变量名称相同
	 */
	@RequestMapping("/itemEdit/{id}")
	public String itemEdit(@PathVariable("id") Integer id, HttpServletRequest reuqest, 
			 Model model) throws Exception{
		
		//String idStr = reuqest.getParameter("id");
		Items items = itmesService.findItemsById(id);
		
		//Model模型:模型中放入了返回给页面的数据
		//model底层其实就是用的request域来传递数据,但是对request域进行了扩展.
		model.addAttribute("item", items);
		
		//如果springMvc方法返回一个简单的string字符串,那么springMvc就会认为这个字符串就是页面的名称
		return "editItem";
	}

改造支持restful

<td><a href="${pageContext.request.contextPath }/items/itemEdit/${item.id}">修改</a></td>

return "redirect:itemEdit/"+items.getId();

静态资源访问mvc:resources

如果在DispatcherServlet中设置url-pattern为 /则必须对静态资源进行访问处理。
spring mvc 的<mvc:resources mapping="" location="">实现对静态资源进行映射访问。
如下是对js文件访问配置:
<mvc:resources location="/js/" mapping="/js/**"/>

7.拦截器:

作用:拦截请求,一般做登录权限验证时用的比较多
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

1)需要编写自定义拦截器类,实现HandlerInterceptor接口
2)在spirngMvc.xml中配置拦截器生效

拦截器定义 用户身份认证 LoginInterceptor.java

public class LoginInterceptor implements HandlerInterceptor {

	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
		//判断当前访问路径是否为登录的路径,如果是则放行
		String url=request.getRequestURI();
		if(url.indexOf("/login") > 0){
			return true;
		}
		
		//判断session中是否有登录信息,如果没有则跳转到登录页面,如果有则放行
		HttpSession session = request.getSession();
		if(session.getAttribute("username") != null){
			return true;
		}
		
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		return false;
	}

}

拦截器配置 <mvc:mapping path="/**"/>

<!-- 配置拦截器 -->
	<mvc:interceptors>
		<!-- 多个拦截器的执行顺序等于springMvc.xml中的配置顺序 -->
<!-- 		<mvc:interceptor> -->
			<!-- 拦截请求的路径    要拦截所有必需配置成/** -->
<!-- 			<mvc:mapping path="/**"/> -->
			<!-- 指定拦截器的位置 -->
<!-- 			<bean class="cn.itheima.interceptor.Interceptor1"></bean> -->
<!-- 		</mvc:interceptor> -->
		
<!-- 		<mvc:interceptor> -->
			<!-- 拦截请求的路径    要拦截所有必需配置成/** -->
<!-- 			<mvc:mapping path="/**"/> -->
			<!-- 指定拦截器的位置 -->
<!-- 			<bean class="cn.itheima.interceptor.Interceptor2"></bean> -->
<!-- 		</mvc:interceptor> -->
		
		<mvc:interceptor>
			<!-- 拦截请求的路径    要拦截所有必需配置成/** -->
			<mvc:mapping path="/**"/>
			<!-- 指定拦截器的位置 -->
			<bean class="cn.itheima.interceptor.LoginInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

运行流程

在这里插入图片描述

8.登录权限验证:

1)编写登录的controller, 编写跳转到登录页面的方法,  编写登录验证方法
2)编写登录页面
3)编写拦截器

运行过程:
1)访问随意一个页面,拦截器会拦截请求,会验证session中是否有登录信息
如果已登录,放行
如果未登录,跳转到登录页面
2)在登录页面中输入用户名,密码,点击登录按钮,拦截器会拦截请求,如果是登录路径放行
在controller方法中判断用户名密码是否正确,如果正确则将登录信息放入session

LoginController.java

@Controller
@RequestMapping("/login")
public class LoginController {

	//跳转到登录页面
	@RequestMapping("/login")
	public String login() throws Exception{
		return "login";
	}
	
	@RequestMapping("/submit")
	public String submit(String username, String pwd ,HttpServletRequest request) throws Exception{
		
		HttpSession session = request.getSession();
		//判断用户名密码的正确性,如果正确则将登录信息放入session中
		//这里简写,真正项目中需要去数据库中校验用户名和密码
		if(username != null){
			session.setAttribute("username", username);
		}
		
		//跳转到列表页
		return "redirect:/items/list";
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值