zoukankan      html  css  js  c++  java
  • SpringMVC_day02

    SpringMVC_day02

    1. 高级参数绑定

    1.1 绑定数组

    需求:接收要批量删除的商品的id。

    Controller方法中可以用Integer[ ]或QueryVo的private Integer[] ids属性接收,此对象属性名要与页面name属性值相同。

    controller: 
    public ModelAndView delItems2(QueryVo vo) {}
    jsp: <c:forEach items="${itemList }" var="item">
    	<tr><td><input type="checkbox" name="ids" value="${item.id}"/></td>...</tr>
    </c:forEach>
    //页面中选中多个checkbox向controller方法传递ids
    

    1.2 绑定List集合

    需求:实现对商品数据的批量修改。

    Controller方法中用QueryVo的private List itemList属性接收。

    接收List类型的数据必须是pojo的属性,如果方法的形参为ArrayList类型无法正确接收到数据。

    controller: public ModelAndView delItems2(QueryVo vo) {}
    jsp的name属性必须是list属性名+下标+元素属性名
    jsp:
    <c:forEach items="${itemList }" var="item" varStatus="status">
    <tr>
    	<td><input type="checkbox" name="itemList[${status.index }].id" value="${item.id }"/></td>
    	<td><input type="text" name="itemList[${status.index }].name" value="${item.name }"/></td>
    	...
    </tr>
    </c:forEach>
    

    ${current} 当前这次迭代的(集合中的)项

    ${status.first} 判断当前项是否为集合中的第一项,返回值为true或false

    ${status.last} 判断当前项是否为集合中的最

    varStatus属性常用参数总结下:

    ${status.index} 输出行号,从0开始。

    ${status.count} 输出行号,从1开始。

    ${status.后一项,返回值为true或false

    begin、end、step分别表示:起始序号,结束序号,跳跃步伐。

    2. @RequestMapping

    通过@RequestMapping注解可以定义不同的处理器映射规则。

    2.1 URL路径映射

    2.1.1 添加到方法上

    @RequestMapping(value="item")或@RequestMapping("/item")/可省略
    public String delItems(QueryVo vo) {}
    value的值是数组,可以将多个URL映射到同一个方法。
    @RequestMapping(value={"item1", "item2"})
    

    2.1.2 添加到类上

    //在class上添加@RequestMapping(url)指定通用请求前缀,限制此类下的所有方法请求url必须以请求前缀开头
    @RequestMapping("/item")
    public class ItemsController {}
    

    2.2 请求方法限定

    ​ 除了可以对url进行设置,还可以限定请求进来的方法。

    --限定GET方法
    @RequestMapping(value="/updateitem.action",method=RequestMethod.GET)
    如果通过POST访问则报错:
    HTTP Status 405 - Request method 'POST' not supported
    --限定POST方法
    @RequestMapping(value="/updateitem.action",method=RequestMethod.POST)
    --限定GET和POST方法
    @RequestMapping(value="/updateitem.action",method = {RequestMethod.GET,RequestMethod.POST})
    不写则默认支持RequestMethod的八种方法
    

    3. Controller方法返回值

    3.1 返回ModelAndView

    详见SpringMVC_day01

    3.2 返回void

    在Controller方法形参上可以定义request和response,使用request或response指定响应结果。

    --使用request转发页面
    request.getRequestDispatcher("/WEB-INF/jsp/itemList.jsp").forward(request, response);
    --使用response重定向页面
    response.sendRedirect("/14.2SpringMVC/success.jsp");
    --使用response直接显示
    response.getWriter().print("hahaha");
    

    3.3 返回字符串

    3.3.1 返回逻辑视图名

    controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。

    //指定逻辑视图名,经过视图解析器解析为jsp路径:/WEB-INF/jsp/itemList.jsp
    return "itemList";
    

    3.3.2 redirect重定向

    //转发到修改此商品页面
    //重定向后地址栏变为重定向的地址,行了新的request和response,所以之前的请求参数都会丢失
    return "redirect:/itemEdit.action?id="+item.getId();
    

    3.3.3 forward转发

    // 转发后地址栏还是原来的请求地址,没有执行新的request和response,之前的请求参数都存在
    return "forward:/itemEdit.action";
    

    3.4 三种返回值对比

    1.ModelAndView 带着数据及返回视图路径。不建议使用,因为数据和视图耦合了。
    2.String 返回视图路径,model携带数据。推荐使用,解耦,数据和视图分离。
    3.void ajax请求,异步请求时使用。
    

    4. 异常处理器

    SpringMVC在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。

    4.1 异常处理思路

    系统中异常包括两类:预期异常运行时异常RuntimeException(如int i=1/0),前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

    系统的dao、service、controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理,如下图:

    4.2 自定义异常类

    ​ 为了区别不同的异常,通常根据异常类型进行区分,创建一个自定义系统异常。如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。

    public class MyException extends Exception {
    	private String msg;//存放异常信息
    	public String getMsg() {
    		return msg;
    	}
    	public void setMsg(String msg) {
    		this.msg = msg;
    	}
    	public MyException(String msg) {
    		super();
    		this.msg = msg;
    	}
    }
    

    4.3 自定义异常处理器

    public class CustomHandlerException implements HandlerExceptionResolver {
    	@Override
    	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
    			Exception exception) {
    		//自定义异常信息
    		String msg;
    		//判读异常类型
    		if(exception instanceof MyException) {
    			//如果是自定义异常,读取异常信息
    			msg=((MyException) exception).getMsg();
    			//msg=exception.getMessage();
    		}else {
    			//如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
    			Writer out=new StringWriter();
    			PrintWriter pw=new PrintWriter(out);
    			exception.printStackTrace(pw);
    			msg=out.toString();
    		}
    		ModelAndView mav=new ModelAndView();
    		mav.addObject("msg", msg);
    		mav.setViewName("exception");
    		return mav;
    	}
    

    4.4 异常处理器配置

    在springmvc.xml中添加:

    <!--配置全局异常处理器-->
    <bean id="customHandlerException" class="com.itheima.exception.CustomHandlerException"/>
    

    5. 上传图片

    5.1 配置图片虚拟目录

    • 在tomcat上配置

      在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:

      在浏览器访问如localhost:8080/pic/1.jpg即可访问D:developupload emp下的图片。

    • 在eclipse中配置

      双击tomcat,打开modules,. . .,复制一张图片到该文件夹,浏览器访问测试。

    5.2 导入jar包

    实现图片上传需要加入的jar包:

    5.3 配置上传解析器

    在springmvc.xml中配置文件上传解析器:

    <!--配置上传解析器,id固定-->
    	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    		<!--设置文件上传大小限制,如为5M-->
    		<property name="maxUploadSize" value="5242880"/>
    	</bean>
    

    5.4 修改jsp页面

    form表单必须设置enctype属性:enctype="multipart/form-data"

    5.5 实现图片上传

    @RequestMapping("updateItems")
    	//MultipartFile picFile用于接收上传的图片
    	public String updateItems(Items item,MultipartFile picFile) throws IllegalStateException, IOException {
    		//设置图片名称,不能重复
    		String picName=UUID.randomUUID().toString();
    		
    		//获取上传的图片名称
    		String originalName=picFile.getOriginalFilename();
    		//获取上传的图片后缀
    	//String suffix=originalName.substring(originalName.lastIndexOf("."));//.jpg
    		String suffix=FilenameUtils.getExtension(originalName);//jpg
    		
    		//保存图片
    		picFile.transferTo(new File("D:\JavaEE\04.Tomcat\img\"+picName+"."+suffix));
    		//设置图片名到商品中
    		item.setPic(picName+"."+suffix);
    		//更新商品
    		this.itemsService.updateById(item);
    		//转发到修改此商品页面
    		return "redirect:/itemEdit.action?id="+item.getId();
    	}
    

    6. json数据交互

    6.1 @RequestBody, @ResponseBody

    /*
    @RequestBody注解接收http请求的json数据,将json数据转换为java对象进行绑定。
    @ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
    */
    	@RequestMapping("testJson")
    	public @ResponseBody Items testJson(@RequestBody Items item) {
    		//@ResponseBody设置将返回的数据转为json格式
    		//@RequestBody将传入的json数据封装到Items对象上
    		return item;
    	}
    

    6.2 SpringMVC加入json支持

    导入jar包:

    6.3 配置json转换器

    在springmvc.xml中

    --method1:使用注解驱动
    <mvc:annotation-driven />
    --method2:不适用注解驱动
    <!--处理器适配器 -->
    	<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>
    

    7. RESTful

    7.1 什么是RESTful

    一种资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    资源:互联网所有的事物都可以被抽象为资源

    资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。分别对应 添加、 删除、修改、查询。

    传统方式操作资源
    http://127.0.0.1/item/queryItem.action?id=1	查询,GET
    http://127.0.0.1/item/saveItem.action			添加,POST
    http://127.0.0.1/item/updateItem.action		修改,POST
    http://127.0.0.1/item/deleteItem.action?id=1	删除,GET或POST
    
    使用RESTful操作资源
    http://127.0.0.1/item/1		查询,GET
    http://127.0.0.1/item		添加,POST
    http://127.0.0.1/item		修改,PUT
    http://127.0.0.1/item/1		删除,DELETE
    传统方式每次请求的地址都在做描述,如查询时是queryItem,添加时是saveItem,修改时是updateItem,删除时是deleteItem。为了不做描述,所以使用RESTful风格。
    

    7.2 RESTful演示

    使用RESTful风格开发的接口,根据id查询商品,接口地址是:localhost:8080/item/1,从url上获取商品id,步骤如下:

    1. 使用注解@RequestMapping("item/{id}")声明请求的url;{xxx}叫做占位符

    2. 使用(@PathVariable() Integer id)获取url上的数据

    @RequestMapping("/itemEdit/{id}.action")
    public ModelAndView queryById(@PathVariable Integer id) {}
    /*
    如果@RequestMapping中表示为"item/{id}",id和形参名称一致,@PathVariable不用指定名称。如果不一致,例如"item/{ItemId}"则需要指定名称@PathVariable("itemId")
    */
    //浏览器访问localhost:8080/14.2SpringMVC/itemEdit/1.action
    

    注意两个区别

    1. @PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)

    2. 如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,目前返回的json数据。如果不加,就走视图解析器,返回页面。

    8. 拦截器

    8.1 定义

    SpringMVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

    8.2 自定义拦截器类

    public class HandlerInterceptor1 implements HandlerInterceptor {
    	 //controller执行前调用,return true表示继续执行,false终止执行,
    	 //这里可以加入登录校验,权限拦截等。
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
    		return true;
    	}
    	//controller执行后但视图未返回前调用,
    	//这里可以对模型数据进行加工处理,如加入公用信息以便页面显示。
    	@Override
    	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
    			throws Exception {
    		System.out.println("1_postHandle");
    	}
    	//controller执行且视图返回后调用,
    	//这里可得到执行controller时的异常信息,也可记录操作日志
    	@Override
    	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
    			throws Exception {
    		System.out.println("1_afterCompletion");
    	}
    }
    

    8.3 拦截器配置

    在springmvc中配置拦截器:

    <mvc:interceptors>
    		<!--配置拦截器1-->
    		<mvc:interceptor>
    			<!--设置所有请求都进入拦截器
    			"/*" 是拦截所有的文件夹,不包含子文件夹
    			"/**" 是拦截所有的文件夹及里面的子文件夹-->
    			<mvc:mapping path="/**"/>
    		<bean class="com.itheima.handlerInterceptor.HandlerInterceptor1"></bean>
    		</mvc:interceptor>
    		<!--配置拦截器2-->
    		<mvc:interceptor>
    		<mvc:mapping path="/**"/>
    		<bean class="com.itheima.handlerInterceptor.HandlerInterceptor2"></bean>
    		</mvc:interceptor>
    	</mvc:interceptors>
    

    8.4 测试

    浏览器访问localhost:8080/14.2SpringMVC/itemList.action

    HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true
    运行结果如下:
    1_preHandle
    从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且Controller也不执行了。
    
    HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false
    运行结果如下:
    1_preHandle
    2_preHandle
    1_afterCompletion
    从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。
    
    HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回true
    运行结果如下:
    1_preHandle
    2_preHandle
    2_postHandle
    1_postHandle
    2_afterCompletion
    1_afterCompletion
    

    preHandle按拦截器定义顺序调用,postHandler按拦截器定义逆序调用,afterCompletion按拦截器定义逆序调用。

    postHandler在拦截器链内所有拦截器返成功调用,afterCompletion只有preHandle返回true才调用。

    拦截器定义顺序取决于springmvc配置的顺序

    9. 拦截器应用

    需求: 拦截用户请求,判断用户是否登录(登录请求不能拦截),如果用户已经登录,放行;如果用户未登录,跳转到登录页面。

    public class HandlerInterceptor1 implements HandlerInterceptor {
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
    		//判断用户是否登录,如果没有登录,重定向到登录页面,不放行;如果登录,放行
    		//url:http://localhost:8080/14.2SpringMVC/login.action
    		//uri:/login.action
    		//注意:不拦截登录请求(即uri中包含"login"的)
    		String uri=request.getRequestURI();
    		if(!uri.contains("login")) {
    			//获取用户名
    			String username=(String)request.getSession().getAttribute("username");
    			//判断用户名是否为空
    			if(username==null) {
    				//不放行,跳转到登录界面
    response.sendRedirect(request.getContextPath()+"/toLogin.action");
    				return false;
    			}
    		}
    		return true;
    	}
    	...
    }
    
  • 相关阅读:
    web学生选课平台
    YUM仓库的搭建
    定制RPM包
    会话保持
    Nginx负载均衡器+keepalived
    LAMP搭建配置
    KVM安装搭建
    安装PHP以及搭建博客(四)伪静态
    安装PHP以及搭建博客(三)服务迁移分离
    安装PHP以及搭建博客(二)
  • 原文地址:https://www.cnblogs.com/ALiWang/p/12482718.html
Copyright © 2011-2022 走看看