springMVC学习笔记---day04-上传图片、JSON转对象、校验、全局异常、拦截器、静态资源

一:使用springmvc上传图片

步骤分析:
a:导入commons-fileupload.jar和commons-io.jar
b:在springmvc的配置文件中配置多部件解析器
c:需要在方法的形参中添加一个参数接受上传文件,参数的类型为MultiPartFile,要求参数名称和input控件的name属性一致
d:jsp的form表单中需要添加enctype属性
1.导入文件上传需要的jar包

2.分析当上传图片时,选中图片以后点击"打开"按钮触发的事件是什么?

onchange事件

a、编写jsp页面中的上传图片框

<body>
	<div class="body-box" style="float: right">
		<form id="jvForm" action="edit.do" method="post">
			<tr>
				<td width="20%" class="pn-flabel pn-flabel-h">
					<span class="pn-frequired">*</span> 
					上传商品图片(90x150尺寸):
				</td>
				<td width="80%" class="pn-fcontent">注:该尺寸图片必须为90x150。
				</td>
			</tr>
			<tr>
				<td width="20%" class="pn-flabel pn-flabel-h">
				</td>
				<td width="80%" class="pn-fcontent">
					<img width="100" height="100" id="allUrl" src="/res/img/pic/ppp.jpg" /> 
					<input type="file" name="pic" οnchange="uploadPic()" />
				</td>
			</tr>
		</form>
	</div>
</body>

b、引入jquery.js和jquery.form.js插件

<!-- 引入jquery.js和jquery.form.js插件 -->
<script src="${pageContext.request.contextPath}/res/common/js/jquery.js" type="text/javascript"></script>
<script src="${pageContext.request.contextPath}/res/common/js/jquery.form.js" type="text/javascript"></script>

c、编写上传的function

<script type="text/javascript">

	 //上传图片
	function uploadPic(){
		var options = {
				url : "${pageContext.request.contextPath}/upload/uploadPic.do",
				type : "post",
				dataType : "text",
				success : function(data){
					//图片的路径
					$("#allUrl").attr("src", data);
				}
		}
		//使用jquery.form.js插件模拟一个form进行提交
		$("#jvForm").ajaxSubmit(options);
	} 
</script>


d、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>
<link href="${pageContext.request.contextPath}/res/itcast/css/admin.css" rel="stylesheet" type="text/css"/>
<link href="${pageContext.request.contextPath}/res/common/css/theme.css" rel="stylesheet" type="text/css"/>
<link href="${pageContext.request.contextPath}/res/common/css/jquery.validate.css" rel="stylesheet" type="text/css"/>
<link href="${pageContext.request.contextPath}/res/common/css/jquery.treeview.css" rel="stylesheet" type="text/css"/>
<link href="${pageContext.request.contextPath}/res/common/css/jquery.ui.css" rel="stylesheet" type="text/css"/>

<!-- 引入jquery.js和jquery.form.js插件 -->
<script src="${pageContext.request.contextPath}/res/common/js/jquery.js" type="text/javascript"></script>
<script src="${pageContext.request.contextPath}/res/common/js/jquery.form.js" type="text/javascript"></script>
<script type="text/javascript">

	 //上传图片
	function uploadPic(){
		var options = {
				url : "${pageContext.request.contextPath}/upload/uploadPic.do",
				type : "post",
				dataType : "text",
				success : function(data){
					//图片的路径
					$("#allUrl").attr("src", data);
				}
		}
		//使用jquery.form.js插件模拟一个form进行提交
		$("#jvForm").ajaxSubmit(options);
	} 
</script>
</head>
<body>
	<div class="body-box" style="float: right">
		<form id="jvForm" action="edit.do" method="post">
			<tr>
				<td width="20%" class="pn-flabel pn-flabel-h">
					<span class="pn-frequired">*</span> 
					上传商品图片(90x150尺寸):
				</td>
				<td width="80%" class="pn-fcontent">注:该尺寸图片必须为90x150。
				</td>
			</tr>
			<tr>
				<td width="20%" class="pn-flabel pn-flabel-h">
				</td>
				<td width="80%" class="pn-fcontent">
					<img width="100" height="100" id="allUrl" src="/res/img/pic/ppp.jpg" /> 
					<input type="file" name="pic" οnchange="uploadPic()" />
				</td>
			</tr>
		</form>
	</div>
</body>
</html>

e、在springmvc的核心配置文件中配置上传图片

	<!-- 配置上传图片
		id 的名称必须为 multipartResolver : 通过此名称才能找到MultiparFile接口的实现类
	 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置上传图片的大小  默认单位为 B -->
		<property name="maxUploadSize" value="1048576"/>
	</bean>

f、编写Controller类

package com.ssm.controller;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

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

import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

/**
 * 上传图片的Controller
 * @author Administrator
 *
 */
@Controller
@RequestMapping(value = "/upload")
public class UploadController {

	//跳转到上传图片页面
	@RequestMapping(value="/upload.do")
	public String up(){
		return "upload";
	}
	
	//上传图片
	@RequestMapping(value = "/uploadPic.do")
	public void uploadPid(@RequestParam(required = false) MultipartFile pic, HttpServletRequest request
			,HttpServletResponse response) throws Exception{
		System.out.println(pic.getOriginalFilename());
		//图片名称生成策略:精确到毫秒+3位随机数
		//生成时间
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		String name = df.format(new Date());
		//生成三位随机数
		Random r = new Random();
		for (int i = 0; i < 3; i ++) {
			int a = r.nextInt(10);//生成10以内的随机数
			name += a;
		}
		//获取文件扩展名
		String extName = FilenameUtils.getExtension(pic.getOriginalFilename());
		//获取项目路径
		String url = request.getSession().getServletContext().getRealPath("/");
		//图片的相对与项目的路径
		String path = "/upload/" + name + "." + extName;
		//执行保存图片的方法,后面是文件夹
		pic.transferTo(new File(url + path));
		//图片显示的路径,需要在页面上图片的src属性使用
		String p = request.getContextPath() + path;
		response.setContentType("application/json;charset=UTF-8");
		response.getWriter().write(p);
		
	}
}

二:JSON和对象之间的相互转化

响应json数据的实现分析:

a:需要在方法上使用@ResponseBody注解

b:方法的返回值需要是一个pojo,就会自动转换成json数据

c:需要导入jackson的jar包

1.导入json支持包

注意:
当在springmvc核心配置文件中使用<mvc:annotation-driven/>标签替代处理器映射器和处理器适配器时就不需要再配置json支持,否则还需要在导入jar包后进行配置
2. 编写jsp页面中的JavaScript,发送ajax数据,接收返回数据并显示
<script type="text/javascript">
	//页面加载完成后执行的函数
	$(function(){
		var url = "${pageContext.request.contextPath}/json/text.do"
		var params = '{"username":"熊大","address":"森林"}';
		//post提交ajax
		$.ajax({
			url : url,
			type : "post",//提交方式
			contentType : "application/json;charset=UTF-8",//设置发送的数据类型为json格式,ajax默认发送key:value格式的数据
			dataType : "json",//设置接收的数据类型为json格式
			data : params,
			success : function(data){
				alert(data.sex);
			}
			
		});
	});
3.编写Controller层代码
package com.ssm.controller;

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

import com.ssm.pojo.User;

/**
 * JSON和对象的相互转化
 * @author Administrator
 *
 */
@Controller
@RequestMapping(value = "/json")
public class JsonController {

	/**
	 * JSON与对象的相互转化需要用到两个标签
	 * @RequestBody		将传入的JSON格式的字符串转化为对象
	 * @ResponseBody	将传出的对象转化为JSON格式的字符串
	 */
	@RequestMapping(value = "/text.do")
	public @ResponseBody User //将User转换成JSON字符串并传递到jsp页面
		jsonToObject(@RequestBody User user){//将页面传递的json字符串自动对应User中的属性封装到User中
		
		System.out.println(user);
		
		user.setSex("雄");
		return user;
	}
}


4.控制台打印数据

5.jsp页面弹出数据

6.@ResponseBody注解详解

(1)、如果返回值是POJO类型,那么@ResponseBody注解会调用MappingJacksonHttpMessageConverter类自动将POJO转成json字符串,同时设置content-type:application/json;charset=utf-8。

        MappingJacksonHttpMessageConverter作用:

a、将pojo调用MappingJackson工具类的api方法,转成json字符串.

b、设置 content-type:application/json;charset=utf-8。

c、通过Response对象获取writer流,将json字符串输出到页面

 

(2)、如果返回值是String类型,那么@ResponseBody注解会调用StringHttpMessageConverter类返回字符串,并设置content-type:text/plain;charset=utf-8。

        String HttpMessageConverter作用:

a、设置 content-type:text/plain;charset=utf-8。

b、通过Response对象获取writer流,将json字符串输出到页面

三:springmvc的校验

1.导入jar包

springmvc校验使用的是Hibernate的校验方式,因此需要导入hibernate的校验支持包


2.在springmvc核心配置文件中配置校验器
	<!-- 处理器映射器,处理器适配器 
		使用该配置可以替代处理器适配器和处理器映射器的配置-->
	<mvc:annotation-driven validator="validator" />
	
	<!-- 配置校验器 -->
	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
		<!-- 使用hibernate的校验器 -->
		<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
		<!-- 指定校验结果的中文存放的properties文件位置 -->
		<property name="validationMessageSource" ref="messageSource"/>
	</bean>
	
	<!-- 校验错误信息的配置文件 -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<!-- 资源文件名 -->
		<property name="basenames">
			<list>
				<!-- 存放中文校验结果的properties文件 -->
				<value>classpath:message</value>
			</list>
		</property>
		<!-- 资源文件的编码格式 -->
		<property name="fileEncodings" value="utf-8" />
		<!-- 对资源文件内容的缓存时间,单位是 s -->
		<property name="cacheSeconds" value="120"/>
	</bean>

3.在需要校验的类的属性字段上添加校验条件 -- 此处以商品为例 Items

public class Items {
    private Integer id;

    @Size(min=1,max=5,message="{itemsNameSize}")//设置最小长度,最大长度以及错误提示
    @NotNull(message="{itemsName}")
    private String name;

    private Float price;

    private String pic;

4.编写properties文件存放错误信息

5.在controller层需要校验参数的前面加上@Validated注解,并且绑定结果

	@RequestMapping(value="/items/edit.do")
	public String toEdit(@Validated Items items,BindingResult result, Model model){//设置给Items进行校验,并且绑定结果
		//获取错误集
		List<ObjectError> allErrors = result.getAllErrors();
		for (ObjectError objectError : allErrors) {
			System.out.println(objectError.getDefaultMessage());
		}
		
		return "redirect:/items/list.do";
	}

四:全局异常处理

全局异常处理的分析:

a:实现 HandlerExceptionResolver 接口

b:在接口的实现类中处理异常

c:配置全局异常处理器

1.在springmvc核心配置文件中自定义异常处理类

	<!-- 自定义全局异常处理类 -->
	<bean class="com.ssm.common.exception.GlobalException"></bean>

2.编写自定义异常处理类
package com.ssm.common.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 GlobalException implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object obj, Exception exception) {
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("error","异常");
		//设置错误跳转页面位置
		modelAndView.setViewName("error/error");
		return modelAndView;
	}

}
3.在controller方法中必须要有异常throws

	@RequestMapping(value="items.do")
	public String listItems(Model model) throws Exception {
		int i = 1 / 0;
		List<Items> list = itemService.list();
		model.addAttribute("list", list);
		return "list";
	}

五:拦截器的使用

1.首先说明:配置多个拦截器时拦截器的执行顺序

preHandle按拦截器定义顺序调用   1    2

postHandler按拦截器定义逆序调用  2  1

afterCompletion按拦截器定义逆序调用 2   1

控制台执行打印顺序如图:



postHandler在拦截器链内所有拦截器返成功调用

afterCompletion只有preHandle返回true才调用

2.编写自定义拦截器的类
package com.ssm.common.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 CustomInterceptor implements HandlerInterceptor {  
  
    /** 
     * 完成之后的处理,返回ModelAndView即页面渲染之后执行的方法
     * 该方法只能做异常处理 
     */  
    @Override  
    public void afterCompletion(HttpServletRequest arg0,  
            HttpServletResponse arg1, Object arg2, Exception arg3)  
            throws Exception {  
        // TODO Auto-generated method stub  
  
    }  
  
    /** 
     * 执行handler之后,返回ModelAndView之前执行的方法 
     */  
    @Override  
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,  
            Object arg2, ModelAndView arg3) throws Exception {  
  
    }  
  
    /** 
     * 执行Handler之前执行的方法 
     * 返回值决定是否拦截,返回true:放行      返回false:拦截
     */  
    @Override  
    public boolean preHandle(HttpServletRequest request,  
            HttpServletResponse response, Object obj) throws Exception {  
        // 设置路径为 /login.do的不拦截  
        String uri = request.getRequestURI();  
        if(uri.indexOf("login") != -1){  
            return true;  
        }else{  
            //判断用户是否登录  
            Object obje = request.getSession().getAttribute("USER_NAME");  
            if(obje != null){  
                return true;  
            }else{  
                //重定向到登录页面  
                response.sendRedirect(request.getContextPath() + "/login.do");  
                return false;  
            }  
        }  
    }  
  
} 


3.在springmvc核心配置文件中配置拦截器

	<!-- 配置springmvc拦截器 -->
	<mvc:interceptors>
		<!-- 可配置多个拦截器 -->
		<mvc:interceptor>
			<!-- 配置当前拦截器的拦截规则   /*/** 表示拦截WEB-INF下的所有文件下的所有扩展名的文件 -->
			<mvc:mapping path="/*/**"/>
			<!-- 执行拦截方法的类 -->
			<bean class="com.ssm.common.interceptor.CustomInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

4.编写登录的Controller层代码
package com.ssm.controller;

import javax.servlet.http.HttpServletRequest;

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

/**
 * 登录控制层
 * @author Administrator
 *
 */
@Controller
public class LoginController {

	//去登录页面
	@RequestMapping(value = "/login.do", method = RequestMethod.GET)
	public String toLogin(){
		return "login";
	}
	
	//提交登录的方法
	@RequestMapping(value = "/login.do", method = RequestMethod.POST)
	public String login(HttpServletRequest request){
		request.getSession().setAttribute("USER_NAME", "已登录");
		
		return "redirect:/items.do";
	}
}

六:静态资源映射

1.问题分析:
当web.xml中配置了拦截路径是 "/" 的时候,将会拦截除了jsp之外的所有资源,但是例如css和js之类的静态资源我们不希望拦截,这个时候就需要配置静态资源映射
2.在springmvc核心配置文件中添加静态资源映射
	<!-- 静态资源映射
		location:静态资源的位置
		mapping:url中包含静态资源请求的路径,及如果url中的请求路径是/js/**时候,将会映射到location中,**表示多级目录
	 -->
	<mvc:resources location="/WEB-INF/js/" mapping="/js/**"></mvc:resources>







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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值