**SpringMVC 笔记二 [共二篇,史上最全重点]*

版权声明:文章为作者自己原创文章,转载请注明出处。 https://blog.csdn.net/qq_37128049/article/details/83449384

今日内容:

1. 响应
2. 文件上传
3. 异常处理
4. 拦截器[作用不大了,了解]

响应

1. 概述:就是把后台的数据返回给浏览器/用户;
2. 搭建环境:
	1. 创建项目:Maven->选择骨架或者手动添加..		在main中创建java,resources,webapp三个包,webapp包下创建WEB-INF,pages:创建succes.jsp;[成功的返回页面]
	2. 导入相关坐标..	[可以应用版本锁定]
	3. 引入前端控制器[固定写法] 
	4. springmvc.xml:开启注解扫描,视图解析器,注解支持
	5. 删除webapp中的index.jsp重新创建一个;
3. 响应数据和结果视图:
	1. Controller方法返回字符串   【使用Model存入数据再返回】
		1. 解析: Controller方法执行后,返回的字符串根据视图解析器所前后拼接的文件名和地址,就能成功的跳转到所需的页面;
		2. jsp页面接收对象:
		* 在Controller方法中,使用model.addAttribute("user",user)			[该方法需传入一个Model]
		* Model不需要我们创建,这是框架为我们生成的;
		* isELIgnored="false" [识别el表达式]
		* 使用${user.username}进行取值...
		* 示例:
		* @Controller
		* @RequestMapping("/user")
		* public class UserController {
		* /**
		* *请求参数的绑定
		* */
		* @RequestMapping(value="/initUpdate")
		* public String initUpdate(Model model) {
		* // 模拟从数据库中查询的数据
		* User user = new User();
		* user.setUsername("张三");
		* user.setPassword("123");
		* user.setMoney(100d);
		* user.setBirthday(new Date());
		* model.addAttribute("user", user);
		* return "update";
		* }
		* }
	2. Controller方法返回void 		【return;】
		1. 请求转发:请求转发是一次请求,不能简写	[手动跳动转发,不会触动视图解析器,需要自己写全路径和文件格式]  
			* 示例:request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
		2. 重定向:请求转发是可以直接访问web-inf下的文件,所以不用写虚拟地址;
			* reponse.sendRedirect(request.getContextPath()+"WEB-INF/pages/xxx.jsp")
		3. 解决中文乱码:
			* reponse.setCharacterEncoding("UTF-8");
			* response.setContentType("text/html;charset=UTF-8");
		4. 直接响应:
			* response.getWriter().print("你好");
		5. 注意:程序运行到响应,那么响应后面的代码应写上return;
			* 一次请求对应一次响应,所以response.getWriter.print("xxx"),里面打印的需要在整个方法执行完才会整体的去响应,在此之前它是将打印的语句储备起来,还未发送响应;所以使用return;进行结尾,那么就可以不让框架继续执行其他,直接返回;
		6. 使用框架后,request,response这些以后都不经常用了;
		7. 为什么domain实体类要实现Serializable接口?
			* 它是实体类,专门用来存储类,它存在于内存中,实现序列化接口,可以将封装好的类保存到硬盘中,如果突然断电关机什么意外情况,可以反序列化还原;
			* 实现该接口,才可以将该对象远程调用,远程传输到其他的服务器,传输时以流的形式
		8. 实体类中的常见问题:
			1. 如果实体类中写了有参构造,那么需要再为它创建一个无参构造;
			2. 成员变量最好使用private修饰,加强安全性,只能通过get,set对其操作;
			3. 成员变量尽量使用包装类型,不要使用基本类型,即尽量使用Integer类,而不使用int基本类型; 
			4. Integer修饰的变量可以为空,但基本类型不能为null;	比如:private Integer ge=null;
	3. ModelAndView:
		1. 把user对象储存到mv对象中,也会把user对象存入到request对象;
		2. 它既可以储存键值对[发挥model],它也可以转发视图[view]的作用;
			* 示例:
			* @RequestMapping("/testModelAndView")
			* public ModelAndView testModelAndView(){
			* ModelAndView mv =new ModelAndView();
			* System.out.println("testModelAndView方法执行了...")
			* User user=new User();
			* user.setUsername("小枫")
			* user.setPassword(123);
			* user.setAge(30);
			* mv.addObject("user",user);
			* mv.setViewName("success");
			* reutrn mv;
			* }
	4. 使用关键字的方式进行转发或者重定向		[使用关键字是不会被视图解析器所管理,需要自己手动补全路径]
		* @RequestMapping("/testForwardOrRedirect")
		* public String testForwardOrRedirect(){
		* //请求的转发:
		* return "forward:/WEB-INF/pages/success.jsp";
		* //重定向
		* return "redirect:/index.jsp";
		* }
4. ResponseBody响应json数据
	1.  DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置:
		* //前端控制前,哪些资源不拦截:
		* <mvc:resources location="/css/" mapping="/css/**"/>
		* <mvc:resources location="/images/" mapping="/images/**"/>
		* <mvc:resources location="/js/" mapping="/js/**"/>
	2. 特点:
		1. mvc:resources标签配置不过滤
		2. location元素表示webapp目录下的包下的所有文件
		3. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b

5. 模拟示例:
	1. 模拟异步请求响应:		
		1. 服务器:
			* @RequestMapping("/testAjax")
			* public void testAjax(@RequestBody String body){
			* //
			* System.out.println(body);
			* }
		2. 浏览器:
			* $(function(){
			* $("#btn").click(funcation(){
			* $.ajax({
			* url:""user/testAjax",
			* contextType:"application/json;charset=UTF-8",				//设置了这种格式,提交是以json格式提交,如果不以此设置,$.get |$.post 则都是表单提交格式
			* data:'{"username":"heihei","password":"123","age":30}',
			* dataType:"json",
			* type:"post",
			* success:function(date){
			* //data服务器端响应的json数据,进行解析。
			* }
			* })
			* })
		3. 如果传入已经定义好了的domain里User实体类,那么也可以直接传入这个实体类,只要属性值对应的上,那么springmvc就会自动绑定,与ajax发送的属性值一一对应;

文件上传

1. 文件上传三要素:    [只要是文件上传,就必须满足这三个要素]
	1. form表单的enctype取值必须是:multipart/form-data
		* [默认值是:application/x-222-form-urlencoded]
		* enctype:是表单请求正文的类型
	2. method属性必须是post		
		* get请求会把文件携带在地址栏上,而get请求是有大小限制的;
	3. 提供一个文件选择域而且必须有name属性:
		* <input type="file">  
2. 借助第三方组件实现文件上传:
	* 导入commons-fileupload-1.3.1.jar和commons-io-2.4.jar
3. 案例实现:
	1. 搭建开发环境:
			1. 创建一个新的maven项目:
				* 坐标,springmvc.xml,web.xml
				* <dependency>
					<groupId>commons-fileupload</groupId>
					<artifactId>commons-fileupload</artifactId>
					<version>1.3.1</version>
					</dependency>
					<dependency>
					<groupId>commons-io</groupId>
					<artifactId>commons-io</artifactId>
					<version>2.4</version>
					</dependency>
			2. 补全包路径
			3. 编写文件上传的JSP页面:
				<h3>文件上传</h3>
				<form action="user/fileupload" method="post" enctype="multipart/form-data">
				选择文件:<input type="file" name="upload"/><br/>
				<input type="submit" value="上传文件"/>
				</form>
			4. 编写文件上传的Controller控制器:
				* @RequestMapping(value="/fileupload")
					public String fileupload(HttpServletRequest request) throws Exception {
					// 先获取到要上传的文件目录
					String path = request.getSession().getServletContext().getRealPath("/uploads");
					// 创建File对象,一会向该路径下上传文件
					File file = new File(path);
					// 判断路径是否存在,如果不存在,创建该路径
					if(!file.exists()) {
					file.mkdirs();
					}
					// 创建磁盘文件项工厂
					DiskFileItemFactory factory = new DiskFileItemFactory();
					ServletFileUpload fileUpload = new ServletFileUpload(factory);
					// 解析request对象
					List<FileItem> list = fileUpload.parseRequest(request);
					// 遍历
					for (FileItem fileItem : list) {
					// 判断文件项是普通字段,还是上传的文件
					if(fileItem.isFormField()) {
					}else {
					// 上传文件项
					// 获取到上传文件的名称
					String filename = fileItem.getName();
					// 上传文件
					fileItem.write(new File(file, filename));
					// 删除临时文件
					fileItem.delete();
					}
					}
					return "success";
					}
5. SpringMVC实现原理分析:
	1. 选择文件后点击上传;
	2. 当文件上传后,通过request进入到前端控制器
	3. 前端控制器通过添加的配置文件解析器,解析request并返回upload
	4. 前端控制器调用Controller,将upload传入Controller类下的fileuoload2(MultipartFile upload),然后对其进行操作;
	5. 注意:前端的name属性值必须和后端Controller类下finduoload2内传入的参数名保持一致;
6. 实现代码:
	1. SpringMVC传统方式文件上传:
		1. SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名必须和表单file标签的name属性相同;
		2. 代码如下:
			@RequestMapping(value="/fileupload2")
			public String fileupload2(HttpServletRequest request,MultipartFile upload) throws
			Exception {
			System.out.println("SpringMVC方式的文件上传...");
			// 先获取到要上传的文件目录
			String path = request.getSession().getServletContext().getRealPath("/uploads");
			// 创建File对象,一会向该路径下上传文件
			File file = new File(path);
			// 判断路径是否存在,如果不存在,创建该路径
			if(!file.exists()) {
			file.mkdirs();
			}
			// 获取到上传文件的名称
			String filename = upload.getOriginalFilename();
			String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
			// 把文件的名称唯一化
			filename = uuid+"_"+filename;
			// 上传文件
			upload.transferTo(new File(file,filename));
			return "success";
			}
		3. 配置文件解析器对象:		【如果是传统的文件上传那么会报错,只有SpringMVC的文件上传才能起作用】
			<!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
			<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
			<property name="maxUploadSize" value="10485760"/>             // 10485760=1024*1024*10=10MB
			</bean>
			

	2. SpringMVC跨服务器文件上传:
		1. 搭建图片服务器:
			1. 根据文档配置tomcat9的服务器,现在是两个服务器
			2. 导入资料中day02_SpringMVC5_02image项目,作为图片服务器使用		[两个tomcat模拟两台服务器,一台服务器作为控制器接收请求,一台服务器作为图片储存]
		2. 实现SpringMVC跨服务器文件上传
1. 导入开发需要的jar包:
					    <dependency>
						<groupId>com.sun.jersey</groupId>
						<artifactId>jersey-core</artifactId>
						<version>1.18.1</version>
						</dependency>
						<dependency>
						<groupId>com.sun.jersey</groupId>
						<artifactId>jersey-client</artifactId>
						<version>1.18.1</version>
						</dependency>
				2. 编写文件上传JSP页面:
						<h3>跨服务器的文件上传</h3>
						<form action="user/fileupload3" method="post" enctype="multipart/form-data">
						选择文件:<input type="file" name="upload"/><br/>
						<input type="submit" value="上传文件"/>
						</form>
				3. 编写控制器:
						@RequestMapping(value="/fileupload3")
						public String fileupload3(MultipartFile upload) throws Exception {
						System.out.println("SpringMVC跨服务器方式的文件上传...");
						// 定义图片服务器的请求路径
						String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
						// 获取到上传文件的名称
						String filename = upload.getOriginalFilename();
						String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
						// 把文件的名称唯一化
						filename = uuid+"_"+filename;
						// 向图片服务器上传文件
						// 创建客户端对象
						Client client = Client.create();
						// 连接图片服务器
						WebResource webResource = client.resource(path+filename);
						// 上传文件
						webResource.put(upload.getBytes());
						return "success";
						}

异常处理

1. SpringMVC异常处理流程:
	1. 浏览器-> 前端控制器-> web-> service-> dao
	2. 如果出现错误,默认处理方案是将错误依次往上抛出:
		* 假如dao层出现错误,会抛给service->web->前端控制器->浏览器
	3. 出现错误如果将错误出现在浏览器上,会降低用户体验,产生不好的影响;
		* 此时可在前端控制器添加一个异常处理器组件,它将从内部抛给前端控制器的异常拦截,并将异常进行处理,返回给浏览器一个友好的错误提示页面;
	4. Controller调用service,service调用dao,异常都是向上抛出的,最终有DispathcherServlet找异常处理器进行异常的处理。
	5. 示例:
1. 自定义异常类:
				package cn.itcast.exception;
				public class SysException extends Exception{
				private static final long serialVersionUID = 4055945147128016300L;
				// 异常提示信息
				private String message;
				public String getMessage() {
				return message;
				}
				public void setMessage(String message) {
				this.message = message;
				}
				public SysException(String message) {
				this.message = message;
				}}
			2. 自定义异常处理器
				package cn.itcast.exception;
				import javax.servlet.http.HttpServletRequest;
				import javax.servlet.http.HttpServletResponse;
				import org.springframework.web.servlet.HandlerExceptionResolver;
				import org.springframework.web.servlet.ModelAndView;
				/**
				* 异常处理器
				* @author rt
				*/
				public class SysExceptionResolver implements HandlerExceptionResolver{
				/**
				* 跳转到具体的错误页面的方法
				*/
				public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse
				response, Object handler,
				Exception ex) {
				ex.printStackTrace();
				SysException e = null;
				// 获取到异常对象
				if(ex instanceof SysException) {
				e = (SysException) ex;
				}else {
				e = new SysException("请联系管理员");
				}
				ModelAndView mv = new ModelAndView();
				// 存入错误的提示信息
				mv.addObject("message", e.getMessage());
				// 跳转的Jsp页面
				mv.setViewName("error");
				return mv;
				}
				}
			3. 配置异常处理器:
				< bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolvaer"/>

拦截器

1. SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理;
2. 拦截器链:(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
3. 解释:
	* 过滤器:是servlet规范中的一部分,任何java web工程都可以使用。
	* 拦截器:是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
	* 过滤器:是在url-pattern中配置了/*之后,可以对所有要访问的资源拦截;
	* 拦截器:它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦截的。
	* 它也是AOP思想的具体应用。
	* 我们要想自定义拦截器,要求必须实现:HandlerInterceptor接口。
4. 不同点:过滤器什么都拦截,而拦截器只能拦截特定的;即过滤器的范围大于拦截器;

猜你喜欢

转载自blog.csdn.net/qq_37128049/article/details/83449384
今日推荐