SpringMVC框架–学习笔记(下)

SpringMVC框架–学习笔记(下)

接上篇:SpirngMVC框架–学习笔记(上):https://blog.csdn.net/a745233700/article/details/81038382

17、全局异常处理:

    系统中异常包括两类,预期异常和运行时异常RuntimeException,前者通过捕获异常从而获得异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

    系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

SpringMVC框架--学习笔记(下)

springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

(1)自定义异常类:

对不同的异常类型定义异常类,继承Exception

//自定义异常:
//针对预期的异常,需要在此类中抛出此类的异常
public class CustomException extends Exception{
	
	private String message;
	public CustomException(String message)
	{
		super(message);
		this.message=message;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
}

(2)全局异常处理器:实现HandlerExceptionResolver接口

思路:

    系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。

    全局控制器处理思路:

    ①解析出异常类型;

    ②如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示。

    ③如果该异常不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)

//自定义异常:
//针对预期的异常,需要在此类中抛出此类的异常
public class CustomException extends Exception{
	
	private String message;
	public CustomException(String message)
	{
		super(message);
		this.message=message;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
}

在springmvc文件中注册全局异常处理器:

       <!-- 全局异常处理器 -->
       <!-- 不用写id,系统根据是否实现HandlerExceptionResolver接口,
       		只要实现,就是全局异常处理器,如果配置多个,只有一个起作用 -->
       <bean class="com.zwp.ssm.exception.CustomExceptionResolver"></bean> 

SpringMVC框架--学习笔记(下)

如果与业务功能相关的异常,建议在service中抛出异常。

与业务功能没有关系的异常,建议在controller中抛出。

18、上传图片:

(1)创建图片虚拟目录:

①第一种:

SpringMVC框架--学习笔记(下)

②第二种:

也可以直接修改tomcat的配置:在conf/server.xml文件,添加虚拟目录:

SpringMVC框架--学习笔记(下)

注意:在图片虚拟目录中,一定将图片目录分级创建(提高I/O性能),一般我们采用按日期进行分级创建。

(2)加入上传图片的jar包:

SpringMVC框架--学习笔记(下)

(3)在页面的form表单中加入enctype=”multipart/form-data”

SpringMVC框架--学习笔记(下)

(4)在springmvc.xml文件中配置解析器:

       <!-- 上传文件 -->
       <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
       		<!-- 设置上传文件最大尺寸 -->
       		<property name="maxUploadSize">
       			<value>5242880</value>
       		</property>
       </bean>

(5)编写Controller:

	//MultipartFile items_pic用于接收图片
	@RequestMapping(value="/editItemsSubmit",method={RequestMethod.POST,RequestMethod.GET})
	public String editItemsSubmit(Model model,HttpServletRequest request,Integer id,
			@ModelAttribute("itemsCustom") @Validated(value={ValidGroup1.class}) ItemsCustom itemsCustom,
			BindingResult bindingResult,MultipartFile items_pic) throws Exception
	{
		
		if(bindingResult.hasErrors())
		{
			List<ObjectError> allErrors=bindingResult.getAllErrors();
			//自定义一个list接受自己编码后的提示字符串,在把自己定义的list传到界面,
            //这样就解决了把乱码传到界面的问题了
            List<String> listErrors=new ArrayList<>();

			for(ObjectError objectError:allErrors)
			{
				//System.out.println(objectError.getDefaultMessage());
				//把返回错误的提示再次编码
				String strError=new String(objectError.getDefaultMessage().getBytes("ISO-8859-1"),"UTF-8"); 
	            listErrors.add(strError);//把编码好的错误提示信息加自己定义好list集合里面去
			}
			model.addAttribute("allErrors", listErrors);
			return "Items/editItems";
		}
		
		//原始名称
		String originalFilename=items_pic.getOriginalFilename();
		System.out.println(originalFilename);
		//上传图片:
		if(items_pic!=null && originalFilename!=null && originalFilename.length()>0)
		{
			//存储图片的物理路径:
			String pic_path="D:\\Tomcat 5.5\\pictures\\";
		
			//新的图片名称
			String newFileName=UUID.randomUUID()+originalFilename.substring(originalFilename.lastIndexOf("."));
			//新图片:
			File newFile=new File(pic_path+newFileName);
	
			//将内存中的数据写入磁盘
			items_pic.transferTo(newFile);
			
			//将新图片名称写到itemsCustom中
			itemsCustom.setPic(newFileName);
		}
		
		//调用service更新商品信息,页面需要将商品信息传到此方法中
		itemsService.updateItems(id, itemsCustom);
				
		//页面转发:
		return "forward:queryItems.action";
	}

(6)页面显示:

SpringMVC框架--学习笔记(下)

19、json交互:

@RequestBody:将json串转成java对象

@ResponseBody:将java对象转成json输出。

(1)请求是Json串,输出也是json串。

SpringMVC框架--学习笔记(下)

(2)请求是key/value,输出是json(常用)

SpringMVC框架--学习笔记(下)

最终结果都是输出json数据,为了在前端页面方便对请求结果进行解析。

步骤:

第一步:导入jar包依赖:

SpringMVC框架--学习笔记(下)

第二步:配置json转化器:

在注解适配器中加入messageConverters

SpringMVC框架--学习笔记(下)

注意:如果使用<mvc:annotation-driver />则不用定义上边的内容。

第三步:页面和控制器:

SpringMVC框架--学习笔记(下)

SpringMVC框架--学习笔记(下)

SpringMVC框架--学习笔记(下)

SpringMVC框架--学习笔记(下)

SpringMVC框架--学习笔记(下)

SpringMVC框架--学习笔记(下)

SpringMVC框架--学习笔记(下)

20、springmvc对RESTful的支持:

(1)对url进行规范,写RESTful格式的url

SpringMVC框架--学习笔记(下)

(2)http的方法规范 :

不管是删除、添加、更新。。使用的url是一致的,如果进行删除,需要设置http的方法为delete,同理添加。

后台controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。

(3)对http的contentType规范:

请求是指定contentType,要json数据,设置成json格式的type..

需求:查询商品信息,返回json数据。

思路:定义方法,进行url映射使用RESTful风格的url,将查询商品的信息的id传入controller。输出json是,使用@ResponseBody将java对象输出json。

(1)Controller:

SpringMVC框架--学习笔记(下)

	//根据id查找商品信息,使用RESTful风格,并返回json格式的数据
	//("/itemView/{id}")的id要和@PathVariable("id")的id一致,表示将("/itemView/{id}")的id绑定到@PathVariable后面的参数上面
	@RequestMapping("/itemView/{id}")
	public @ResponseBody ItemsCustom itemView(@PathVariable("id") Integer id) throws Exception
	{
		ItemsCustom itemsCustom=itemsService.findItemsById(id);
		return itemsCustom;
	}

(2)前端控制器配置:

	<!-- RESTful规范要用第二种方式: -->
	<servlet>
		<servlet-name>springmvc_restful</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
			
		<!-- contextConfigLocation:配置springmvc加载的配置文件(处理处映射器、处理器适配器等等) -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:/spring/springmvc.xml</param-value>
		</init-param>	 
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc_restful</servlet-name>
		<!-- 
		第一种:*.action,访问以.action结尾由DispatcherServlet进行解析
		第二种:/,所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置
				不让DispatcherServlet进行解析,使用此种方法可以实现RESTful风格的url
		第三种:/*,这种配置不对,使用这种配置,最终要转发到一个jsp页面,仍然会由
					DispatcherServlet解析jsp,不能根据jsp页面找到Handle,会报错-->
		<url-pattern>/</url-pattern>
	</servlet-mapping>

(3)访问的url:

SpringMVC框架--学习笔记(下)

(4)json结果数据:

SpringMVC框架--学习笔记(下)

–对静态资源的解析:

在springmvc.xml中添加静态资源的解析:

      <!-- 对静态资源的解析,如js,css,img... -->
      <!--  <mvc:resources location="/js/" mapping="/js/**"></mvc:resources> -->
      <!--  <mvc:resources location="/css/" mapping="/css/**"></mvc:resources> -->

对静态资源的访问:

SpringMVC框架--学习笔记(下)

21、springmvc拦截器:

(1)定义拦截器:实现HandlerInterceptor接口

public class HandlerInterceptor1 implements HandlerInterceptor{
	
	//进入Handler方法之前
	//用于身份认证,身份授权
	//比如身份认证,如果认证不通过表示当前用户没有登陆,需要此方法拦截不再向下执行
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {	
		//return false:表示拦截,不向下执行
		//return ture:表示放行
		System.out.println("HandlerInterceptor1...preHandle");
		return true;
	}

	//进去Handler方法之后,返回modelAndView之前执行
	//应用场景:将公用的模型数据(比如菜单导航)传到视图,也可以在这里统一制定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
		System.out.println("HandlerInterceptor1...postHandle");
	}
	
	//执行Handler完成执行此方法
	//应用场景:统一异常处理,统一日志处理
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("HandlerInterceptor1...afterCompletion");
	}
}

(2)配置拦截器:

①针对HandlerMapping进行拦截配置:(一般不用)

如果在某个HandlerMapping中配置,经过该HandlerMapping映射成功的Handler最终使用该拦截器。

SpringMVC框架--学习笔记(下)

②类似全局的拦截器:

springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。

       <!-- 拦截器 -->
       <mvc:interceptors>
       		<!-- 多个拦截器:顺序执行 -->
      	 	<mvc:interceptor>
      	 		<!-- /**:表示拦截所有url包括子url路径 -->
       			<mvc:mapping path="/**"/>
       			<!-- 拦截器路径 -->
       			<bean class="com.zwp.ssm.intercept.HandlerInterceptor1"></bean>
      	 	</mvc:interceptor>
      	 	
      	 	<mvc:interceptor>
       			<mvc:mapping path="/**"/>
       			<bean class="com.zwp.ssm.intercept.HandlerInterceptor2"></bean>
      	 	</mvc:interceptor>    	 	
       </mvc:interceptors>

(3)测试:

①两个拦截器都放行:

SpringMVC框架--学习笔记(下)

总结:preHandle方法按顺序执行;postHandle和afterCompletion按拦截器配置的逆向顺序执行。

②拦截器1放行,拦截器2不放行:

SpringMVC框架--学习笔记(下)

总结:拦截器1放行,拦截器2的preHandle才会执行;

拦截器2的preHandle不放行,拦截器2的postHandle和afterCompletion不会执行;

只要有一个拦截器不放行,postHandle不会执行。

③拦截器1不放行,拦截器2不放行:

SpringMVC框架--学习笔记(下)

总结:拦截器1的preHandle不放行,postHandler和afterCompletion不会执行。

拦截器1的preHandle不放行,拦截器2不执行。

(4)拦截器小结:

根据测试结果,对拦截器应用。

比如:统一日志处理拦截器,需要该拦截器的preHandle一定要放行,且将它放在拦截器链中第一个位置。

比如:登陆认证拦截器,放在拦截器链中第一个位置;权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过之后才检验权限)

(5)拦截器应用:

需求:

①用户请求url

②拦截器进行拦截校验:

    –如果请求的url是公开地址(无需登陆即可访问的url),让放行。

    –如果用户session不存在,跳转到登陆页面

    –如果用户session存在,放行,继续操作。

登陆页面:

<form action="${pageContext.request.contextPath }/login.action" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登陆"/>
</form>

拦截器:

public class LoginInterceptor implements HandlerInterceptor{
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {	
		//获取请求的url
		String url=request.getRequestURI();
		//判断url是否是公开地址(实际使用时,将公开地址配置在配置文件中)
		//这里公开地址是登陆提交的地址
		if(url.indexOf("login.action")>=0){
			//如果进行登陆提交,放行
			return true;
		}
		//判断session
		HttpSession session=request.getSession();
		//从session中取出用户身份信息:
		String username=(String) session.getAttribute("username");
		if(username!=null)
		{	//身份存在,放行
			return true;
		}	
		//执行到这里,表示用户身份需要认证,跳转到登陆界面
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);	
		return false;		
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3) throws Exception {

	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3)
			throws Exception {
	}
}

注册拦截器:

       <!-- 拦截器 -->
       <mvc:interceptors>
       		<!-- 多个拦截器:顺序执行 -->
       		<mvc:interceptor>
      	 		<!-- /**:表示拦截所有url包括子url路径 -->
       			<mvc:mapping path="/**"/>
       			<!-- 拦截器路径 -->
       			<bean class="com.zwp.ssm.intercept.LoginInterceptor"></bean>
      	 	</mvc:interceptor>
       </mvc:interceptors>

编写Controller:

@Controller
public class LoginController {
	@RequestMapping("/login")
	public String login(HttpSession sesison,String username,String password) throws Exception{
		//调用service进行身份验证
		//...
		
		//保存用户身份信息
		sesison.setAttribute("username", username);
		//重定向到商品列表
		return "redirect:items/queryItems.action";	
	}
	
	@RequestMapping("/logout")
	public String logout(HttpSession sesison) throws Exception{
		
		//清除session
		sesison.invalidate();
		//重定向商品列表
		return "redirect:items/queryItems.action";		
	}
}

登陆成功页面:

SpringMVC框架--学习笔记(下)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114726.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • vue双向绑定数组和对象有什么区别_后端接收前端json数据

    vue双向绑定数组和对象有什么区别_后端接收前端json数据众所周知,vue中v-model会忽略所有表单元素的value、checked、selectedattribute的初始值而总是将Vue实例的数据作为数据来源。大部分情况,v-model是绑定一个对象的属性,但是如果数据库中的数据是一个数组,这种情况下,如果把数组转换成对象再绑定,然后再转换回去提交到数据库显然是一件工程量很大的事情,本着程序员偷懒的原则,我发现了一个便捷的方法,废话不多说,直接上干货。HTML代码如下:<!DOCTYPEhtml><htmllan.

  • ssm框架过时了吗_ssm和mvc框架

    ssm框架过时了吗_ssm和mvc框架日志如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的助手曾经:sout,debug现在:日志工厂掌握STDOUT_LOGGINGLOG4Jlog4j什么是Log4j?我们可以控制日志信息输送的目的地是控制台我们也可以控制每一条日志的输出格式通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。分页减少数据量selsect * from user limit startIndex,pageS

  • Spring中的注解 @RequestBody和@ResponseBody的使用和区别

    Spring中的注解 @RequestBody和@ResponseBody的使用和区别一、@RequestBody@RequestBody的作用是将前端传来的json格式的数据转为自己定义好的javabean对象如图以微信小程序为例,前端向后端传入如下json格式的数据需要注意的是传入数据的属性名称要和后端javabean中定义的一致发送请求后可以看到在控制台中我们通过javabean对象的get方法打印出了前端传来的值,说明json数据已经成功的被转换为了javab…

  • 机器学习 Lasso回归算法「建议收藏」

    机器学习 Lasso回归算法「建议收藏」Lasso回归算法:坐标轴下降法与最小角回归法小结    前面的文章对线性回归做了一个小结,文章在这:线性回归原理小结。里面对线程回归的正则化也做了一个初步的介绍。提到了线程回归的L2正则化-Ridge回归,以及线程回归的L1正则化-Lasso回归。但是对于Lasso回归的解法没有提及,本文是对该文的补充和扩展。以下都用矩阵法表示,如果对于矩阵分析不熟悉,推荐学习张贤达的《矩阵分析与应用》…

  • 把数据库中的静态图片遍历在前端页面上[通俗易懂]

    把数据库中的静态图片遍历在前端页面上[通俗易懂]把数据库中的静态图片遍历在前端页面上先上数据库中数据其次是后端的接口(把所有数据封装到List集合中发送过去):@RequestMapping(value=”/scenicSpots”,method=RequestMethod.GET)publicActionResultfindScenicSpots(){List<ScenicSpots>scenicSpots=scenicSpotService.QueryScenicSpots();

  • 插值法综合实例用matlab解决,matlab 插值法「建议收藏」

    插值法综合实例用matlab解决,matlab 插值法「建议收藏」matlab插值法实验五插值法5.1实验目的掌握插值的基本思想与方法,会借助数学软件Matlab求解并讨论其收敛性.5.2实验内容1、Lagrange插值法、Newton插值法的Matlab求解方法,在对Runge现象的观察基础上,了解高次插值的不稳定性及其改进方法;2、熟悉Matlab中的插值求解函数,掌握三次样条插值的Matlab求解;3、会求解某些简单的实际问题.5.3实验步骤5.5.1…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号