一:使用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>