springMVC(下集)
SpringMVC 的常用注解
SpringMVC 静态资源的处理
SpringMVC 的文件上传和下载
SpringMVC 的统一异常处理
SpringMVC 的拦截器
SpringMVC 的自动校验
1.springmvc常用注解
(1)使用cookie获取页面设置的cookie值,代码示例:
构建页面进行cookie的值的设置
<head>
<script type="text/javascript">
//(path)必须要填写,因为JS的默认路径是当前页,如果不填,此cookie只在当前页面生效!~
document.cookie="name=wwj;path=/"
document.cookie="age=32;path=/"
</script>
</head>
<body>
<a href="testCookie">查看Cookie</a>
</body>
后台业务代码
@Controller
public class CookieController {
@RequestMapping("/testCookie")
public String testCookie(@CookieValue(value = "name", required = false) String name,
@CookieValue(value = "age", required = false) Integer age) {
System.out.println(name + "," + age);
return "hello";
}
}
操作访问,先访问jsp页面进行cookie值的设置。在进行请求的访问
(2)使用@SessionAttributes将数据放入session作用域中
需要注意的是@SessionAttributes只能用在类上
常用的设置@SessionAttributes(value={“user1”, “user2”}) 会将model中属性名为user1和user2的属性添加到会话中
@SessionAttributes(value={"user"})
@Controller
public class SessionController {
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model){
model.addAttribute("user", "wwj");
return "success";
}
}
访问连接,分别在不用的页面进行取值
(3)使用@ModelAttribute
注释在一个普通方法(初始化数据)
//构建一个模型
public class Girl {
private String name;
private int age;
}
@Controller
public class ModelController {
@ModelAttribute("girl")
public Girl init(Model model){
Girl g = new Girl();
g.setAge(28);
g.setName("菲菲");
return g;
}
@RequestMapping("/m1")
public String m1(Model model) {
System.out.println(model.containsAttribute("girl"));
return "msg";
}
}
直接接收restful格式并进行封装
路径请求 <a href="m2/wwj/32">restful操作</a>
接收restful
@RequestMapping("/m2/{name}/{age}")
public String m1(@ModelAttribute Girl girl) {
System.out.println(girl.getName()+girl.getAge());
return "msg";
}
注意数据:数据被封装到modelattr中,同时也是在model中的
(4)设置请求方式 (了解)
@RequestMapping(value=”m3”,method=RequestMethod.POST)
通过method来设置http的请求方式
总结:其实不在乎注解的与多少,毕竟是属于对servlet的包装,可以假定不管使用什么方式,接收到前台所传递的参数
2.springMVC对于静态资源的处理
使用 <mvc:resources> 掌握
静态资源在加载的时候,被拦截了。这个时候需要我们在springmvc中标注哪些为静态资源,不受springmvc进行拦截
<mvc:resources location="/js/" mapping="/js/**"/>
location代表着webcontext容器下路径。映射所有js下面的资源为静态资源
观察浏览器资源加载列表
使用<mvc:default-servlet-handler/>(掌握)
3.SpringMVC的文件上传和下载
文件上传
构建form表单 需要设置enctype(编码格式) 为 multipart/form-data 不仅包含文本数据,还包含文件数据
<!-- 多文件上传 -->
<form action="uploadUrl" method="post" enctype="multipart/form-data">
<input type="file" name="filename" /> <input type="file"
name="filename" /> <input type="submit" value="文件上传" />
</form>
引入对应的jar包
Commons-fileupload.jar和commons-io.jar 2个包属于依赖关系翻译过来就是通用的上传与通用的读写操作
设置对应的上传数据要求在springmvc.xml中
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置请求编码格式,必须与JSP中的pageEncoding属性一致 -->
<property name="defaultEncoding" value="UTF-8" />
<!-- 设置允许上传文件的最大值(2MB),单位为字节 -->
<property name="maxUploadSize" value="2097152" />
</bean>
处理对应上传的处理类
@Controller
public class UploadController {
@RequestMapping("/uploadUrl")
public String handleFormUpload(@RequestParam("filename") MultipartFile[] files,HttpServletRequest req){
//判断文件是否存在
if(files.length>0){
for (MultipartFile multipartFile : files) {
//获取上传文件的原始名字
String originalFilename = multipartFile.getOriginalFilename();
//一般决定于项目设计的时候所规范的路径
String dirPath = req.getServletContext().getRealPath("/upload/");
File filePath = new File(dirPath);
//如果保存文件的地址不存在,就先创建目录
if(!filePath.exists()) {
filePath.mkdirs();
}
String newFilename = UUID.randomUUID()+"_"+originalFilename;
try {
multipartFile.transferTo(new File(dirPath + newFilename));
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
}
注意:UUID 是 通用唯一识别码(Universally Unique Identifier),是一种软件建构的标准
使用ajax进行文件的上传
注意事项:
需要使用到js中一个叫做formData对象
尽量使用goole或者火狐浏览器
function testup(){
var form = new FormData(document.getElementById("tf"));
$.ajax({
url:"uploadUrl1",
type:"post",
data:form,
processData:false,
contentType:false,
success:function(data){
console.log(data)
if(data=="ok"){
alert("上传成功")
}else {
alert("上传失败")
}
}
});
}
注意:contentType 和 processData 设置为false 使其能够正确的对formdata进行处理
文件的下载
构建请求
<a href="downloadone">下载单文件</a>
<a href="downloadmore">下载多文件</a>
构建处理类:
单文件下载
@Controller
public class DownloadController {
@RequestMapping("/downloadone")
public ResponseEntity<byte[]> download(HttpServletRequest req) throws IOException {
// 这个路径由数据库中取出
String resourceName = "计划.txt";
// 指定全路径位置
File file = new File(req.getServletContext().getRealPath("/upload/")+resourceName);
HttpHeaders headers = new HttpHeaders();
// 避免出现文件名乱码
String filename = new String(resourceName.getBytes("iso-8859-1"),"utf-8");
//设置响应的内容 attachment 附件
headers.setContentDispositionFormData("attachment", filename);
// 设置响应的内容为流的方式
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
}
多文件需要考虑进行打包
@RequestMapping("/downloadmore")
public ResponseEntity<byte[]> download1s(HttpServletRequest req) throws IOException {
//数据库中提取
List<String> list = new ArrayList<String>();
list.add("计划.txt");
list.add("进度.txt");
//压缩后的文件名
String resourcesName = "test.zip";
//压缩后的全路径
String pathName = req.getServletContext().getRealPath("/upload/");
File zipFile = new File(pathName+resourcesName);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
//读取并写入到压缩包里面
InputStream input = null;
for (String str : list) {
String name = pathName+str;
input = new FileInputStream(new File(name));
zipOut.putNextEntry(new ZipEntry(str));
int temp = 0;
while((temp = input.read()) != -1){
zipOut.write(temp);
}
input.close();
}
zipOut.close();
File file = new File(pathName+resourcesName);
HttpHeaders headers = new HttpHeaders();
String filename = new String(resourcesName.getBytes("iso-8859-1"),"utf-8");
headers.setContentDispositionFormData("attachment", filename);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
}
4.SpringMVC 的统一异常处理(掌握) (避免在controller中进行冗余的try catch操作)
先自定义异常
/**
* 自定义异常
* @author Yun
*
*/
public class ServiceException extends RuntimeException {
public ServiceException(String msg){
super(msg);
}
}
定义全局异常处理类 (需要用到@ControllerAdvice以及@ExceptionHandler(ServiceException.class))
@ControllerAdvice
public class GlobalExceptionResolver {
/**
* 处理所有业务异常
*
* @param e 业务异常
* @return json结果
*/
@ExceptionHandler(ServiceException.class)
@ResponseBody
public Girl handleOpdRuntimeException(ServiceException e) {
Girl g = new Girl();
g.setAge(18);
g.setName("wwj");
return g;
}
}
controller业务处理
@Controller
public class Econtroller {
/**
* 测试返回异常信息
* @return
*/
@RequestMapping("/exception")
public void returnExceptionInfo() {
if (1 != 2) {
// 用户民错误或不存在异常
throw new ServiceException("错误");
}
}
}
注意:开发中,我们在设计业务功能模块,都需要配置对应的exception处理
注解详解
@ControllerAdvice:在spring3.2中,新增,可以用于定义@ExceptionHandler、@InitBinder、
@ModelAttribute,并应用到所有的@requestMapping中。它相当于对Controller的增强,特使aop机制的事项
5.SpringMVC 拦截器 (掌握) 拦截 Interceptor
拦截器是对过滤器操作的一种升华。拦截器本身的机制也是aop进行实现
操作方式
public class MyInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("preHandle");
return true;
}
}
配置文件
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有的请求,这个必须写在前面,也就是写在【不拦截】的上面 -->
<mvc:mapping path="/**" />
<!-- 但是排除下面这些,也就是不拦截请求 -->
<mvc:exclude-mapping path="/login.html" />
<bean class="com.wwj.interceptor.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
执行的顺序为
preHandle 在业务处理器处理请求之前被调用(如果preHandle返回false)
postHandle 在业务处理器处理请求执行完成后,生成视图之前执行
afterCompletion 完全处理完请求后被调用,可用于清理资源等
6.SpringMVC 的自动校验(了解)
引入相关的jar包
构建实体类 (有一些注解可以对对象的某个字段进行检验)
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class User {
@NotNull(message="id不能为空!")
private int uid;
@NotBlank(message="用户名不能为空!")
private String uname;
}
(将配置文件中拦截器代码剔除)
<form action="user1" method="post">
<input type="text" name="uid"/>
<input type="text" name="uname"/>
<button>提交</button>
</form>
控制代码中通过提供的errorObj来获取验证的信息
@Controller
public class Vcontroller {
@RequestMapping("/user1")
@ResponseBody
public User test(@Validated User user, BindingResult result) {
if (result.hasErrors()) {
List<ObjectError> errors = result.getAllErrors();
for (ObjectError error : errors) {
System.out.println(error.getDefaultMessage());
}
}
return user;
}
}