zoukankan      html  css  js  c++  java
  • 笔记10:springMVC

    三层结构

                                        框架
    表现层(web层):			springMVC
    业务层(service层):		spring
    持久层(dao层):			MyBatis
    

    表现层一般使用MVC设计模型

    M:model模型			例如javaBean等
    V:view视图				例如jsp、html等
    C:Controller控制器 	例如Servlet等
    
    springMVC:基于java实现MVC设计模型的请求驱动类型的轻量级Web框架,属于springFrameWork的后续产品
    

    springMVC和Struts2区别

    相同:都是基于MVC模型编写、底层都离不开原始ServletAPI、处理请求机制都是一个核心控制器
    不同:
    	1-springMVC入口是一个Servlet,struts2是Filter
    	2-springMVC基于方法设计,struts2是基于类,stuts2每次会创建一个动作类,所以springMVC快些
    	3-springMVC使用更简洁,同时支持JSR303,处理ajax请求更方便
    	4-struts2的OGNL表达式使页面开发效率更高些,但执行效率没比JSTL提升,尤其struts2表单标签远没有html执行效率高
    

    springMVC入门程序

    需求:index.jsp点击超链接转发到成功jsp页面
    
    ----搭建开发环境
    	1-导入jar包
    	2-web.xml配置springMVC核心控制器
    		<servlet>
    			<servlet-name>DispatcherServlet</servlet-name>
    			<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    			<init-param><!--初始化加载springmvc配置文件-->
    				<param-name>contextConfigLocation</param-name>
    				<param-value>classpath:springmvc.xml</param-value>
    			</init-param>
    			<load-on-startup>1</load-on-startup>
    		</servlet>
    		<servlet-mapping>
    			<servlet-name>DispatcherServlet</servlet-name>
    			<url-pattern>/</url-pattern>
    		</servlet-mapping>
    	3-创建springmvc配置文件并配置
    		<!-- 配置创建 spring 容器要扫描的包 -->
    		<context:component-scan base-package="cn.xiaoai"></context:component-scan>
    		<!-- 配置视图解析器 -->
    		<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    			<property name="prefix" value="/"></property>
    			<property name="suffix" value=".jsp"></property>
    		</bean>
    		<!--开启spr ingMVC框架注解的支持-->
    		<mvc:annotation-driven></mvc:annotation-driven>
    

    springMVC处理流程:

    1-Request请求,然后进入DispatcherServlet
    2-DispatcherServlet(前端控制器)	
    	--》Handler(处理映射器):返回控制类和对应方法
    	--》HandlerAdapter(处理适配器): 执行方法后并获得请求页面封装成视图模型返回
    	--》ViewResolver(视图解析器):解析视图模型并返回
    	渲染视图并把模型数据填充到request域中
    3-DispatcherServlet最后response响应
    

    【@RequestMapping】注解属性:

    1-value==等于path,表示方法映射路径		
    	valu="/hello"
    2-path==表示方法映射路径					
    	path="/hello"	
    3-method==表示请求的方式 需要一个对象 可以传多个值{},通过RequestMethod.来获得对应方式 
    	method={RequestMethod.POST} 请求为post,方法才执行
    4-params==请求必须携带的参数	
    	params={"username"} 请求必须携带username这个参数,方法才执行
    	params={"username=heihei"} 请求必须携带username这个参数并且值为heihei,方法才执行
    5-heades==限制请求消息头的条件
    	heades={"Accept"} 请求必须包含请求头Accept,方法才执行
    

    请求参数的绑定:

    1-直接在方法参数中定义与传递参数相同名称的参数,(底层通过反射获取方法参数绑定)
    	方法:
    		@RequestMapping("/testParam")
    		public String testParam(String username,String password){
    			System.out.println("----------testParam()执行了");
    			System.out.println(username+"--"+password);
    			return "success";
    		}
    	视图页面:<a href="paramCTL/testParam?username=xiaoai&&password=111111">请求参数的绑定</a>
    2-绑定到JavaBean对象
    	参数名称和bean对象的set方法去掉set首字母小写的名称一致
    	当JavaBean对象引用另一个JavaBean对象,则传参的名称可以多层引用,如:JavaBean对象引用了User对象则可以使用user.xx属性等。
    	方法:
    		@RequestMapping("/saveAccount")
    		public String saveAccount(Account account){
    			System.out.println("----------saveAccount()执行了");
    			System.out.println(account);
    			return "success";
    		}
    	视图页面:
    		<form action="/paramCTL/saveAccount" method="post">
    			姓名:<input type="text" name="username" placeholder="姓名"><br/>
    			密码:<input type="text" name="password" placeholder="密码"><br/>
    			金额:<input type="text" name="money" placeholder="金额"><br/>
    			用户姓名:<input type="text" name="user.uname" placeholder="用户姓名"><br/>
    			用户年龄:<input type="text" name="user.age" placeholder="用户年龄"><br/>
    			<input type="submit"  value="提交"><br/>
    		</form>
    3-绑定到list或map
    	<form action="paramCTL/saveAccount" method="post">
    		姓名:<input type="text" name="username" placeholder="姓名"><br/>
    		密码:<input type="text" name="password" placeholder="密码"><br/>
    		金额:<input type="text" name="money" placeholder="金额"><br/>
    		list用户姓名:<input type="text" name="list[0].uname" placeholder="用户姓名"><br/>
    		list用户年龄:<input type="text" name="list[0].age" placeholder="用户年龄"><br/>
    		map用户姓名:<input type="text" name="map['one'].uname" placeholder="用户姓名"><br/>
    		map用户年龄:<input type="text" name="map['one'].age" placeholder="用户年龄"><br/>
    		<input type="submit"  value="提交"><br/>
    	</form>
    

    springMVC中文乱码的解决:(过滤器)

    ----web.xml中配置
    	<!--配置解决中文乱码的过滤器-->
    	<filter>
    		<filter-name>characterEncodingFilter</filter-name>
    		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    		<init-param>
    			<param-name>encoding</param-name>
    			<param-value>UTF-8</param-value>
    		</init-param>
    	</filter>
    	<filter-mapping>
    		<filter-name>characterEncodingFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    

    自定义类型转换器

    例如:当属性为date类型传入了一个参数字符串为2020-11-11不符合date类型格式时会报错
    	此时需要用自定义类型转换器来完成
    1-先写程序:需要实现Converter接口
    	public class StringToDateConverter implements Converter<String,Date>{
    		/**
    		 *
    		 * @param source 传入的字符串
    		 * @return
    		 */
    		@Override
    		public Date convert(String source) {
    			//判断
    			if (source == null){
    				throw new RuntimeException("请传入数据");
    			}
    			DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    			try {
    				//把字符串转换日期
    				return df.parse(source);
    			} catch (Exception e) {
    				throw new RuntimeException("数据类型转换出现错误");
    			}
    		}
    	}
    2-springMVC.xml配置文件中配置自定义类型转换器(注册)
    	<!--配置自定义类型转换器-->
    	<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    		<property name="converters" >
    			<set><!--添加自定义的类型转换器-->
    				<bean class="cn.xiaoai.utils.StringToDateConverter"></bean>
    			</set>
    		</property>
    	</bean>
    3-使转换器生效
    	<!--开启springMVC框架注解的支持-->
    	<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    

    在核心控制器中拿到servlet原生api

    直接在方法参数里获取即可
    @RequestMapping("/testServlet")
    public String testServlet(HttpServletRequest request, HttpServletResponse response){
        System.out.println("----------testServlet()执行了");
        System.out.println(request);
    
        HttpSession session = request.getSession();
        System.out.println(session);
    
        ServletContext servletContext = session.getServletContext();
        System.out.println(servletContext);
    
        System.out.println(response);
        return "success";
    }
    

    常用注解

    1--【@RequestParam】==把请求中指定名称的参数给控制器中形参赋值
    	属性value:请求参数名称
    	属性required:请求参数中是否必须提供此参数。默认true,表示必须提供,不提供则报错。
    	==使用例子========================================
    	方法:
    		@RequestMapping("/testRequestParam")
    		public String testRequestParam(@RequestParam(value = "name") String username){
    			System.out.println("----------testRequestParam()执行了");
    			System.out.println(username);//输出:xioaai
    			return "success";
    		}
    	页面视图:<a href="anno/testRequestParam?name=xiaoai">RequestParam</a>
    
    2--【@RequestBody】==用于获取请求体内容。直接使用得到是key=value&key=value.....结构的数据  get请求方式不适用
    	属性required:是否必须有请求体。默认true,get请求报错,为false,get请求到null。
    	==使用例子========================================
    	@RequestMapping("/testRequestBody")
    	public String testRequestBody(@RequestBody String body){
    		System.out.println("----------testRequestBody()执行了");
    		System.out.println(body);//输出:username=xxx&age=xxx。xxx为表单里对应的输入值
    		return "success";
    	}
    	页面视图:
    		<form action="anno/testRequestBody" method="post">
    			用户姓名:<input type="text" name="username" placeholder="用户姓名"><br/>
    			用户年龄:<input type="text" name="age" placeholder="用户年龄"><br/>
    			<input type="submit"  value="提交"><br/>
    		</form>
    
    3--【RequestHeader】==用于获取请求消息头	注:实际开发中一般不怎么用
    	属性value:指定消息头名称
    	属性required:是否必须有此消息头
    	==使用例子========================================
    	@RequestMapping("/testRequestHeader")
    	public String testRequestHeader(@RequestHeader(value = "Accept") String header){
    		System.out.println("----------testRequestHeader()执行了");
    		System.out.println(header);
    		return "success";
    	}
    	
    4--【@PathVariable】==绑定url中的占位符。
    	例如:请求url中 /delete/{id},这个{id}就是url占位符。 
    	属性vlue:用于指定url中占位符名称
    	属性required:是否必须提供占位符。
    	==使用例子========================================
    	@RequestMapping("/testPathVariable/{sid}")
    	public String testPathVariable(@PathVariable(name = "sid")String id){
    		System.out.println("----------testPathVariable()执行了");
    		System.out.println(id);//输出10
    		return "success";
    	}
    	视图页面: <a href="anno/testPathVariable/10">PathVariable</a>
    	
    5--【@CookieValue】==获取某个cookie的数据
    	属性value:指定cookie名称
    	属性required:是否必须有此cookie
    	==使用例子========================================
    	public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookieValue){
    		System.out.println("----------testCookieValue()执行了");
    		System.out.println(cookieValue);
    		return "success";
    	}
    	
    6--【@ModelAttribute】
    	属性value:用于获取数据的key。可是pojo的属性名称,也可是map结构的key。
    	----放在方法上:表示当前方法会在控制器的方法执行之前先执行
    		@RequestMapping("/testModelAttribute")
    		public String testModelAttribute(User user){
    			System.out.println("----------testCookieValue()执行了");
    			System.out.println(user);//输出:user信息并且date带有数据
    			return "success";
    		}
    		/**
    		 *由于该方法先执行,直接返回数据即可
    		 * @param uname
    		 * @return
    		 */
    		@ModelAttribute
    		public User showUser(String uname){
    			System.out.println("----------showUser()方法执行了。。");
    			User user = new User();
    			//通过用户查询数据库(模拟)
    			user.setUname(uname);
    			user.setAge(20);
    			user.setDate(new Date());
    			return user;
    		}
    	----放在参数上:获取指定的数据给参数赋值
    		@RequestMapping("/testModelAttribute")
    		public String testModelAttribute(@ModelAttribute("abc") User user){
    			System.out.println("----------testCookieValue()执行了");
    			System.out.println(user);//输出:user信息并且date带有数据
    			return "success";
    		}
    		/**
    		 *把数据存入map,再从map取数据复制赋值给参数
    		 * @param uname
    		 * @return
    		 */
    		@ModelAttribute
    		public void showUser(String uname, Map<String,User> map){
    			System.out.println("----------showUser()方法执行了。。");
    			User user = new User();
    			//通过用户查询数据库(模拟)
    			user.setUname(uname);
    			user.setAge(20);
    			user.setDate(new Date());
    			map.put("abc",user);
    		}
    	
    	视图页面:
    		<form action="anno/testModelAttribute" method="post">
    			用户姓名:<input type="text" name="uname" placeholder="用户姓名"><br/>
    			用户年龄:<input type="text" name="age" placeholder="用户年龄"><br/>
    			<input type="submit"  value="提交"><br/>
    		</form>
    
    7--【@SessionAttribute】==用于多次执行控制器方法间的参数共享。只能作用于类上
    	属性value:指定存入的属性名称
    	属性type:指定存入数据的类型
    	@Controller
    	@RequestMapping("/anno")
    	@SessionAttributes(value = {"SessionAttribute-msg"})//把SessionAttribute-msg=xiaoai存入到session域中
    	public class AnnoController {
    		//存入信息
    		@RequestMapping("/testSessionAttribute")
    		public String testSessionAttribute(Model model){
    			System.out.println("----------testSessionAttribute()执行了");
    			model.addAttribute("SessionAttribute-msg","xioaai");
    			return "success";
    		}
    		//获取信息
    		@RequestMapping("/getSessionAttribute")
    		public String getSessionAttribute(ModelMap modelMap){
    			System.out.println("----------getSessionAttribute()执行了");
    			String SessionAttribute_msg = (String) modelMap.get("SessionAttribute-msg");
    			System.out.println(SessionAttribute_msg);
    			return "success";
    		}
    		//删除信息
    		@RequestMapping("/delSessionAttribute")
    		public String delSessionAttribute(SessionStatus status){
    			System.out.println("----------delSessionAttribute()执行了");
    			status.setComplete();
    			return "success";
    		}
    	}
    

    REST风格URL:

    通过请求方式来判断执行那一个方法
    
    ----当请求路径和请求方法一致时:通过url占位符来判断
    	path = "/user" method="get"
    	findAll()
    	
    	path = "/user/{id}" method="get"
    	findById()
    	
    	localhost:8080/user/10 get  直接带变量10访问即可 不用localhost:8080/user?id=10 get
    	@PathVariable注解即用来取占位符的值
    	
    restful优点:结构清晰、符合标准、易于理解、扩展方便
    

    基于HiddentHttpMethodFilter过滤器

    form表单只支持GET和POST请求,DELETE/PUT等并不支持,
    spring3.0添加了过滤器HiddentHttpMethodFilter可将浏览器请求改为指定请求方式
    通过表单hidden隐藏标签,修改请求方式
    
    其他类如WebClient使用静态方法发送请求,也可模拟各种请求
    

    响应之返回值

    1-String字符串  方法执行并跳转到名称为返回值字符串页面    底层最终也会选择ModelAndView的方式跳转
    	@RequestMapping(value = "/testString")
    	public String testString(Model model){
    		System.out.println("----------testString()执行了。。。");
    		//模拟从数据库中查询出User对象
    		User user = new User();
    		user.setUsername("xiaoai");
    		user.setPassword("123");
    		user.setAge(21);
    		//model对象存入数据
    		model.addAttribute("user",user);
    		return "success";
    	}
    2-void		方法执行,然后再次请求路径
    	@RequestMapping(value = "/testVoid")
    	public void testVoid(Model model){
    		System.out.println("----------testVoid()执行了。。。");
    	}
    	跳转1----可以在视图目录下创建最后一级目录为名称的视图
    	跳转2----请求转发
    		@RequestMapping(value = "/testVoid")
    		public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
    			System.out.println("----------testVoid()执行了。。。");
    			//编写请求转发的语句  请求转发:一次请求,不用编写项目的名称
    			//请求转发不再调用视图解析器,如果有多级目录要手动加上
    			request.getRequestDispatcher("success.jsp").forward(request,response);
    			return;
    		}
    	跳转3----重定向
    		@RequestMapping(value = "/testVoid")
    		public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
    			System.out.println("----------testVoid()执行了。。。");
    			//重定向
    			response.sendRedirect(request.getContextPath()+"/success.jsp");
    			return;
    		}
    	跳转4----直接响应
    		@RequestMapping(value = "/testVoid")
    		public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
    			System.out.println("----------testVoid()执行了。。。");
    			//直接进行响应
    			//--设置中文乱码
    			response.setCharacterEncoding("UTF-8");
    			response.setContentType("text/html;charset=UTF-8");
    			//--响应
    			response.getWriter().print("你好。直接响应");
    			return;
    		}
    
    3--返回值为ModelAndView类型
    	@RequestMapping(value = "/testModelAndView")
    	public ModelAndView testModelAndView(){
    		System.out.println("----------testModelAndView()执行了。。。");
    		//创建ModelAndView对象
    		ModelAndView mv = new ModelAndView();
    		//模拟从数据库中查询出User对象
    		User user = new User();
    		user.setUsername("xiaoai");
    		user.setPassword("123");
    		user.setAge(21);
    		//把user对象存储到mv中,底层也会把user存入到request对象域中
    		mv.addObject("user",user);
    		//跳转到那个页面可以设置
    		mv.setViewName("success");
    		return mv;
    	}
    

    响应之使用forword和redirect

    请求转发和重定向是用不了视图解析的,所以路径问题需要注意
    1--forward
    	@RequestMapping(value = "/testForword")
    	public String testForword(){
    		System.out.println("----------testForword()执行了。。。");
    		return "forward:/susccess.jsp";//路径需要自己手动填写其准确路径
    	}
    2--redirect
    	@RequestMapping(value = "/testRedirect")
    	public String testRedirect(){
    		System.out.println("----------testRedirect()执行了。。。");
    		return "redirect:/suscces.jsp";//通过关键字来重定向返回可以不加项目名,框架默认帮加 
    	}
    

    响应json数据

    1--过滤静态资源
    	默认核心控制器过滤掉了静态资源,需要解决:在springMVC配置文件中配置静态资源不拦截
    	<!--前端控制器,哪些静态资源不拦截-->
    	<mvc:resources location="/css/" mapping="/css/**"/>  <!-- 样式 -->
    	<mvc:resources location="/images/" mapping="/images/**"/>  <!-- 图片 -->
    	<mvc:resources mapping="/js/" location="/js/**"></mvc:resources>
    
    --模拟ajax异步请求
    	$("#btn").click(function () {
    		//发送ajax请求
    		$.ajax({
    			//编写json格式,设置属性和值
    			url:"user/testAjax",
    			contentType:"application/json;charset=UTF-8",
    			data:'{"username":"xiaoai","password":"123","age":"21"}',
    			dataType:"json",
    			type:"post",
    			success:function (data) {
    				//data表示服务器响应的json数据,进行解析
    				alert(data);
    				alert(data.username);
    				alert(data.password);
    				alert(data.age);
    			}
    		});
        });
    	------------------------------------------控制器方法
    	@RequestMapping(value = "/testAjax")
    	public @ResponseBody User testAjax(@RequestBody User user){
    		System.out.println("----------testAjax()执行了。。。");
    		//客户端发送ajax异步请求,传递的是json字符串,后端把json字符串封装到user对象中
    		System.out.println(user);
    		//做响应,模拟查询数据库
    		user.setUsername("haha");
    		user.setAge(31);
    		//做响应
    		return user;
    	}
    

    springMVC提供的文件上传

    1--文件上传回顾:
    	a-form表单enctype(表单请求正文的类型)取值必须是multipart/form-data(默认为:application/x-www-form-urlencoded)
    	b-method属性必须为post
    	c-提供一个文件选择域(<input type="file" /> )
    2--上传原理分析
    	a-form表单enctype取值不是默认,request.getParameter()失效。
    	b-enctype="application/x-www-form-urlencoded"时,form表单正文内容:key=value&key=value&....
    	c-enctype="multipart/form-data"时,form表单正文内容:每部分都是MIME类型描述的正文
    		-----------------------------7de1a433602ac   			分界符 
    		Content-Disposition: form-data; name="userName"  		协议头 
    		aaa              										协议的正文 
    		-----------------------------7de1a433602ac 
    		Content-Disposition: form-data; name="file"; 
    		filename="C:UserszhyDesktopfileupload_demofile.txt" 
    		Content-Type: text/plain         						协议的类型(MIME 类型) 
    		 
    		bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 
    		-----------------------------7de1a433602ac-- 
    		
    3--借助第三方组件实现文件上传
    	使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包:
    	Commons-fileupload 和commons-io。
    	commons-io 不属于文件上传组件的开发 jar 文件,
    	但Commons-fileupload 组件从 1.1 版本开始,它工作时需要 commons-io 包的支持。 
    
    4--传统方式文件上传	
    	@RequestMapping(value = "/fileUpload1")
    	public String fileUpload1(HttpServletRequest request) throws Exception {
    		System.out.println("----------fileUpload1()执行了。。。文件上传");
    		//使用fileupload组件完成文件上传
    		//1-文件上传位置
    		String path = request.getSession().getServletContext().getRealPath("/uploads/");
    		//2-判断该路径是否存在
    		File file = new File(path);
    		if (!file.exists()){
    			file.mkdirs();
    		}
    		//3-解析request对象,获取上传文件项
    		DiskFileItemFactory factory = new DiskFileItemFactory();
    		ServletFileUpload upload = new ServletFileUpload(factory);
    		//解析request
    		List<FileItem> items = upload.parseRequest(request);//全是文件项
    		//遍历
    		for (FileItem item:items){
    			//进行判断,当前item对象是否是上传文件项
    			if (item.isFormField()){ //说明是普通表单项
    
    			}else{ //说明是上传文件项
    				//获取上传文件名称
    				String fileName = item.getName();
    				//把文件名称设置为唯一值
    				String uuid = UUID.randomUUID().toString().replace("-", "");
    				fileName = uuid+"_"+fileName;
    				//完成文件上传
    				item.write(new File(path,fileName));//写到某个路径下
    				item.delete();
    			}
    		}
    		return "success";
    	}
    	视图页面:
    		<form action="fileUploadCTRL/fileUpload1" method="post" enctype="multipart/form-data">
    			选择文件:<input type="file" name="upload" ><br/>
    			<input type="submit" value="上传"><br/>
    		</form>
    5--springMVC方式文件上传
    	----原理分析
    		文件 --》request --》前端控制器 --》配置的文件解析器:解析request,获取上传文件项项返回 --》
    		前端控制器带着上传文件项 --》请求方法:通过MultipartFile类上传
    	a-springMVC配置文件配置组件:
    		<!--配置文件上传解析器 id名称必须为:multipartResolver-->
    		<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    			<property name="maxUploadSize" value="10485760"></property>
    		</bean>
    	b-控制器方法:
    		@RequestMapping(value = "/fileUpload2")
    		public String fileUpload2(HttpServletRequest request,MultipartFile upload) throws Exception {
    			System.out.println("----------fileUpload2()执行了。。。文件上传");
    			//1-文件上传位置
    			String path = request.getSession().getServletContext().getRealPath("/uploads/");
    			//2-判断该路径是否存在
    			File file = new File(path);
    			if (!file.exists()){
    				file.mkdirs();
    			}
    			//获取上传文件名称
    			String fileName = upload.getOriginalFilename();
    			//把文件名称设置为唯一值
    			String uuid = UUID.randomUUID().toString().replace("-", "");
    			fileName = uuid+"_"+fileName;
    			//完成文件上传
    			upload.transferTo(new File(path,fileName));
    			return "success";
    		}
    	c-视图页面:	
    		<form action="fileUploadCTRL/fileUpload2" method="post" enctype="multipart/form-data">
    			选择文件:<input type="file" name="upload" ><br/><%--方法参数名称必须和该name一致--%>
    			<input type="submit" value="上传"><br/>
    		</form>
    
    -------------------------------------------------------以前笔记记录的	
    文件上传和下载
    	--例子1(传统上传)
    		//半框架实现上传
    		@RequestMapping(value = "/up",method = RequestMethod.POST)
    		public String up(@RequestParam("uploadFile") MultipartFile uploadFile ,String desc,HttpSession session) throws IOException {
    			//获取文件上传的名称
    			String fileName = uploadFile.getOriginalFilename();
    			String path = session.getServletContext().getRealPath("photo")+File.separator+fileName;
    			//获取输入输出流
    			InputStream is = uploadFile.getInputStream();
    			OutputStream os = new FileOutputStream(new File(path));
    			//一个一个字节上传
    	//		int i=0;
    	//		while ((i=is.read())!=-1) {
    	//			os.write(i);
    	//		}
    			//字节数组上传
    			int i=0;
    			byte[] flush = new byte[1024];
    			while ((i=is.read(flush))!=-1) {
    				os.write(flush,0,i);
    			}
    			os.close();
    			is.close();
    			return "success";
    		}
    	--例子2(框架直接上传)
    		//利用框架实现上传
    		@RequestMapping(value = "/up_old",method = RequestMethod.POST)
    		public String up_old(@RequestParam("uploadFile") MultipartFile uploadFile ,String desc,HttpSession session) throws IOException {
    			//获取文件上传的名称
    			String fileName = uploadFile.getOriginalFilename();
    			String finalFileName = UUID.randomUUID()+fileName.substring(fileName.lastIndexOf("."));//解决重名问题
    			String path = session.getServletContext().getRealPath("photo")+File.separator+finalFileName;
    			File file = new File(path);
    			uploadFile.transferTo(file);
    			return "success";
    		}
    		
    	--例子(固定图片下载)
    	@RequestMapping(value = "/down")
    	public ResponseEntity<byte[]> down(HttpSession session ) throws IOException{
    		//获取下载文件的路径
    		String realPath = session.getServletContext().getRealPath("img");
    		String finalPath = realPath + java.io.File.separator+"日向雏田.jpg";
    		//读取要下载的文件
    		InputStream is = new FileInputStream(finalPath);
    		byte[] b = new byte[is.available()];//available()获取输入流所读取的文件的最大字节数
    		is.read(b);
    		//设置请求头
    		HttpHeaders headers = new HttpHeaders();
    		headers.add("Content-Disposition", "attachment;filename=zzz.jpg");
    		//设置响应状态
    		HttpStatus statusCode = HttpStatus.OK;
    		ResponseEntity< byte[]> entity = new ResponseEntity<byte[]>(b, headers, statusCode);
    		
    		is.close();
    		return entity;
    	}
    -------------------------------------------------------以前笔记记录的	
    
    6--springMVC跨服务器方式的文件上传
    	1--需要导入相应的jar包(该jar包由sun公司提供)
    		com.sun.jersey:jersey-client:1.18.1
    		com.sun.jersey:jersey-core:1.18.1
    	2--
    		@RequestMapping(value = "/fileUpload3")
    		public String fileUpload3(MultipartFile upload) throws Exception {
    			System.out.println("----------fileUpload3()执行了。。。跨服务器文件上传");
    			//定义上传文件服务器路径
    			String path = "http://localhost:9090/uploads/";
    			//2-判断该路径是否存在
    			File file = new File(path);
    			if (!file.exists()){
    				file.mkdirs();
    			}
    			//获取上传文件名称
    			String fileName = upload.getOriginalFilename();
    			//把文件名称设置为唯一值
    			String uuid = UUID.randomUUID().toString().replace("-", "");
    			fileName = uuid+"_"+fileName;
    			//完成文件上传,跨服务器上传
    			//创建客户端的对象
    			Client client = Client.create();
    			//和图片服务器进行连接
    			WebResource webResource = client.resource(path + fileName);
    			//上传文件
    			webResource.put(upload.getBytes());
    			return "success";
    		}
    

    springMVC异常处理

            产生的异常都是一层一层往上抛出的,不处理最后会抛出到浏览器。
    	异常处理器组件:不把异常抛出到浏览器,通过异常处理器处理异常(把友好错误提示页面响应到浏览器)
    	1--编写自定义异常类(做提示信息)
    		public class SysException extends Exception{
    			//存储提示信息的
    			private String message;
    			@Override
    			public String getMessage() {
    				return message;
    			}
    			public void setMessage(String message) {
    				this.message = message;
    			}
    			public SysException(String message) {
    				this.message = message;
    			}
    		}
    	2--编写异常处理器(需要实现HandlerExceptionResolver接口)
    		public class SysExceptionResolver implements HandlerExceptionResolver{
    			@Override
    			public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {
    				//获取异常对象
    				SysException e = null;
    				if (ex instanceof SysException){
    					e = (SysException) ex;
    				}else{
    					e = new SysException("系统正在维护....");
    				}
    				//创建modelAndView
    				ModelAndView  mv = new ModelAndView();
    				mv.addObject("errorMsg", e.getMessage());
    				mv.setViewName("errorPage");
    				return mv;
    			}
    		}
    	3--配置异常处理器(跳转提示页面) springMVC配置文件配置
    		<!--配置异常处理器-->
    		<bean id="sysExceptionResolver" class="cn.xiaoai.exception.SysExceptionResolver"></bean>
    		
    	4--控制器方法:
    		@RequestMapping(value = "/testException")
    		public String testException() throws SysException{
    			System.out.println("----------testException()执行了。。。异常处理");
    			try {
    				//模拟异常
    				int a = 10/0;
    			} catch (Exception e) {
    				//打印异常信息
    				e.printStackTrace();
    				//抛出自定义异常
    				throw new SysException("服务器走丢了。。。。");
    			}
    			return "success";
    		}
    	5--视图页面:
    		<h3>异常处理页面</h3>
    		<a href="user/testException">异常处理</a>
    		---------------------------------------------
    		<h3>错误页面</h3>
    		${errorMsg}<%--打印错误信息--%>
    

    springMVC拦截器

    ----拦截器类似过滤器filter,可以一个或多个
    	请求--》拦截器(执行放行前代码) --》controller
    	响应《-- 拦截器(执行放行后代码)《-- 	
    	
    ----拦截器和过滤器区别
    	a-过滤器是servlet规范一部分,任何java web工程都能用,拦截器是springMVC框架自己的,只有springMVC框架才能用
    	b-过滤器在url-pattern中配置/*后,所有访问的资源都拦截,拦截器只拦截访问的控制方法,访问的是jsp、html、css、image或js等不会进行拦截
    	
    ----自定义拦截器:
    	1-编写拦截器类(需要实现HandlerInterceptor接口)
    		public class MyInterceptor1 implements HandlerInterceptor{
    			//预处理,放行前执行的方法(controller方法执行前执行)   return false==不放行 true==放行 执行下一拦截器,没有则执行controller中方法
    			@Override
    			public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    				System.out.println("----------MyInterceptor1拦截器执行了。。。。放行之前的代码");
    				return true;
    			}
    			//放行后执行的方法(controller方法执行后执行)
    			@Override
    			public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    				System.out.println("----------MyInterceptor1拦截器执行了。。。。放行之后的代码");
    			}
    			//最后执行的方法
    			@Override
    			public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    				System.out.println("----------MyInterceptor1拦截器执行了。。。。最后执行代码");
    			}
    		}
    	2-配置拦截器(springMVC配置文件中配置)
    		<!--配置拦截器-->
    		<mvc:interceptors>
    			<mvc:interceptor>
    				<mvc:mapping path="/user/*"/><!--要拦截的具体的方法  /**==所有方法都拦截  /user/*==user路径下所有方法拦截-->
    				<!--<mvc:exclude-mapping path=""></mvc:exclude-mapping>&lt;!&ndash;不要拦截的方法&ndash;&gt;-->
    				<!--配置拦截器对象-->
    				<bean id="myInterceptor1" class="cn.xiaoai.interceptor.MyInterceptor1"></bean><!--注册拦截器-->
    			</mvc:interceptor>
    		</mvc:interceptors>
    	
    	----当两个拦截器时执行顺序如下:
    		----------MyInterceptor1拦截器执行了。。。。放行之前的代码
    		----------MyInterceptor2拦截器执行了。。。。放行之前的代码
    		----------testInterceptor()执行了。。。拦截器测试的控制器方法
    		----------MyInterceptor2拦截器执行了。。。。放行之后的代码
    		----------MyInterceptor1拦截器执行了。。。。放行之后的代码
    		----------success.jsp执行了。。。
    		----------MyInterceptor2拦截器执行了。。。。最后执行代码
    		----------MyInterceptor1拦截器执行了。。。。最后执行代码
    

    ---------------------------------------------------------------day3

    ssm整合

    表现层(web层):springMVC框架
    业务层:spring框架
    持久层:myBatis框架
    
    
    一定是用spring框架去整合其他两个框架    写配置文件或注解?怎么简单怎么来    选:配置文件*注解方式
    
    ----1-先配置每个框架,框架可以正常使用。
    
    ----2-spring整合springMVC  
    	思路:service交由spring管理,在控制器方法中可以注入service对象并调用其方法,方法正常使用即spring和springMVC整合成功
    	实现:在web.xml中加载了springMVC的配置文件,但spring配置文件还没有被加载,
    			所以通过监听器把spring配置文件一起加载进来,把service交由spring管理,
    		=====================================web.xml配置文件中配置监听器加载spring配置文件
    		<!--配置spring的监听器, 默认只加载WEB-INF目录下的applicationContext.xml文件-->
    		<listener>
    			<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    		</listener>
    		<!--设置配置文件的路径-->
    		<context-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:applicationContext.xml</param-value>
    		</context-param>
    
    ----3-spring整合myBatis
    	思路:在service层中可以注入dao层并调用其方法,dao层功能实现即spring和myBatis整合成功。
    	实现:在spring配置文件中配置使得spring的ioc容器中有相关dao接口代理对象
    		=====================================spring.xml配置文件中配置整合myBatis
    		<!--spring整合myBatis-->
    		<!--==配置连接池-->
    		<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    			<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    			<property name="jdbcUrl" value="jdbc:mysql:///ssm"></property>
    			<property name="user" value="root"></property>
    			<property name="password" value="root"></property>
    		</bean>
    		<!--==配置sqlSessionFactory对象-->
    		<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    			<property name="dataSource" ref="dataSource"></property>
    		</bean>
    		<!--==配置AccountDao接口所在的包-->
    		<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    			<property name="basePackage" value="cn.xiaoai.dao"></property>
    		</bean>
    
    		<!--配置spring框架声明式事务管理-->
    		<!--===配置事务管理-->
    		<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    			<property name="dataSource" ref="dataSource"></property>
    		</bean>
    		<!--===配置事务通知-->
    		<tx:advice id="txAdvice" transaction-manager="transactionManager">
    			<tx:attributes>
    				<tx:method name="find*" read-only="true"/>
    				<tx:method name="*" isolation="DEFAULT"></tx:method>
    			</tx:attributes>
    		</tx:advice>
    		<!--===配置AOP增强-->
    		<aop:config>
    			<aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.xiaoai.service.impl.*ServiceImpl.*(..))"></aop:advisor>
    		</aop:config>
    
    ----当myBatis的配置文件的配置已经通过spring配置完,则myBatis配置文件可删除。
  • 相关阅读:
    jQuery 设置checkbox全选
    jQuery 判断checkbox是否选中的方法
    jQuery 设置控件的显示与隐藏
    play freamwork 页面的Html+Groovy模板中添加Java代码
    play freamwork 页面的Html+Groovy模板中的if判断
    play freamwork 页面的form表单样式
    获取微信用户列表Openid
    play freamwork 定时任务
    Xitrum学习笔记20
    Xitrum学习笔记19
  • 原文地址:https://www.cnblogs.com/xiaoaiying/p/13344458.html
Copyright © 2011-2022 走看看