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框架--学习笔记(下)

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm导出html_python怎么保存代码

    pycharm导出html_python怎么保存代码pycharm一般安装完毕,就是默认是自动保存的,但是……但是….既然是程序,既然是软件,就难免出现bug。也许会有码友出现头天晚上写好的代码,打开一看,第二天白花花一片!!!最简单的,就是每次编写完毕,习惯按ctrl+s手动保存。但是,提醒你务必检查一下你的设置里面,是不是码友弄好自动保存!步骤如下:菜单File->Settings…->Appeara…

    2022年8月28日
    1
  • Linux学习——浅谈读写锁的使用

    Linux学习——浅谈读写锁的使用一、读写锁是什么?读写锁其实还是一种锁,是给一段临界区代码加锁,但是此加锁是在进行写操作的时候才会互斥,而在进行读的时候是可以共享的进行访问临界区的。读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程。当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步,读写锁的使用规则:只要没有写模式下的加锁,任…

    2022年8月12日
    3
  • linux启动nginx命令_linuxzip解压命令

    linux启动nginx命令_linuxzip解压命令1,首先找到nginx的安装目录whichnginx会找到对应的目录,如图2,查看进程是否存在ps-ef|grepnginx3,杀死进程kill-QUIT1282强制停止kill-912824,进入到nginx的sbin目录,启动nginxcd/usr/local/nginx/sbin/./nginx./nginx-sstop./nginx-squit./nginx-sreload4,但是上面这个..

    2022年10月6日
    0
  • 禁爬虫robots.txt文件[通俗易懂]

    禁爬虫robots.txt文件[通俗易懂]禁止所有爬虫修改根目录robots.txt文件删除所有添加:User-agent:*Disallow:/检测地址:https://tools.aizhan.com/robots/www.lilysilk.org/

    2022年5月18日
    49
  • 不错的BLOG和论坛[通俗易懂]

    不错的BLOG和论坛[通俗易懂]高手的博客阿虚的电子小屋http://hi.baidu.com/aokikyon(从单片机到嵌入式linux都有研究)XY嵌入式Linux  http://blog.chinaunix.net/group/group_1488.html(嵌入式内核研究)嵌入式系统开发Linux+ARMhttp://blog.chinaunix.net/u2/79779/index.html(

    2022年10月2日
    0
  • 海量数据处理的 Top K相关问题「建议收藏」

    海量数据处理的 Top K相关问题「建议收藏」Top-k的最小堆解决方法问题描述:有N(N&gt;&gt;10000)个整数,求出其中的前K个最大的数。(称作Topk或者Top10)问题分析:由于(1)输入的大量数据;(2)只要前K个,对整个输入数据的保存和排序是相当的不可取的。可以利用数据结构的最小堆来处理该问题。最小堆如图所示,对于每个非叶子节点的数值,一定不大于孩子节点的数值。这样可用含有K个节点的最小堆来保存K个目前的最大值(当然根节点是其中的

    2022年6月23日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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