Spring MVC框架

SpringMVC框架

在这里插入图片描述

1、什么是SpringMVC

​ Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。具体更多详细请参考官方文档–>

官方文档(英文):https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html

2、SpringMVC的请求流程

(1)用户发送请求至前端控制器DispatcherServlet

(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;

(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet

(4)DispatcherServlet 调用 HandlerAdapter处理器适配器

(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器)

(6)Handler执行完成返回ModelAndView

(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet

(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;

(9)ViewResolver解析后返回具体View

(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)

(11)DispatcherServlet响应用户

img

总结SpringMVC的工作原理:

  • 客户端发送请求到 DispatcherServlet
  • DispatcherServlet 查询 handlerMapping 找到处理请求的 Controller
  • Controller 调用业务逻辑后,返回 ModelAndView
  • DispatcherServlet 查询 ModelAndView,找到指定视图
  • 视图将结果返回到客户端

3、SpringMVC的优点

(1)可以支持各种视图技术,而不仅仅局限于JSP

(2)与Spring框架集成(如IoC容器、AOP等)

(3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)

(4) 支持各种请求资源的映射策略

4、Spring MVC的主要组件

(1)前端控制器 DispatcherServlet(不需要程序员开发)

​ 作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。

(2)处理器映射器HandlerMapping(不需要程序员开发)

​ 作用:根据请求的URL来查找Handler

(3)处理器适配器HandlerAdapter

​ 注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以 正确的去执行Handler。

(4)处理器Handler(需要程序员开发)

(5)视图解析器 ViewResolver(不需要程序员开发)

​ 作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)

(6)视图View(需要程序员开发jsp)

​ View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)

5、SpringMVC重定向与请求转发

(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"

(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"

6、SpringMVC怎么和Ajax相互调用

通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 :

(1)加入Jackson.jar

(2)在配置文件中配置json的映射

(3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。

7、SpringMVC框架中乱码问题

(1)解决post请求乱码问题:

​ 在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8;

<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>

(2)get请求中文参数出现乱码解决方法有两个:

​ ①修改tomcat配置文件添加编码与工程编码一致,如下:

<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
②另外一种方法对参数进行重新编码:
String userName = 
    new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

注:ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。

8、SpringMVC常用注解

@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径

@RequestBody:注解实现接收http请求的json数据,将json转换为java对象

@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户

@RequestParm : 用于把请求中指定名称的参数给控制器中的形参赋值,也可以说起别名

@PathVaribale : 用于绑定url中的占位符。例如:请求 url 中 /delete/{id},这个**{id}**就是 url 占位符。

@Controller : 用于定义一个控制器类,但需要交给spring管理并且配上@RequestMapping注解才算SpringMVC

​ Controller层 ; 注意控制器类也可以使用@RestController,该注解相当于@ResponseBody +@Controller,表示是表现层,除此之外,一般不用别的注解代替

@Service :用于标注业务层

@Repository : 用于注解dao层,在daoImpl类上面注解。

@Component : 通用注解,当不知道一些类归到哪个层时使用,但是不建议

@Resource@Autowired

@Autowired:就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配(默认是类型匹配)的Bean,并自动注入到相应的地方去。当Spring找不到bean时会抛出异常,将@Autowired注解的required属性设置为false 不会抛出异常,会显示null;当有多个bean对应时,Spring因为不能判定应该使用哪个bean同样会抛出异常,此时使用@Qualifier(“class-name”)注解,即可指定bean

@Resource:默认通过name属性去匹配bean,当找不到时再按type去匹配,当指定了name或者type则根据指定的类型去匹配bean,任何一个不匹配豆浆报错

注意:@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配

@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了;Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

9、SpringMVC拦截器的实现

​ 有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可:

 <!-- 配置SpringMvc的拦截器 -->
 
<mvc:interceptors>
 
    <!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 -->
 
    <bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor"></bean>
 
    <!-- 只针对部分请求拦截 -->
 
    <mvc:interceptor>
 
       <mvc:mapping path="/modelMap.do" />
 
       <bean class="com.zwp.action.MyHandlerInterceptorAdapter" />
 
    </mvc:interceptor>
 
</mvc:interceptors>

实现HandlerInterceptor接口。接口中提供三个方法。

  • preHandle :进入 Handler方法之前执行,用于身份认证、身份授权,比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
  • postHandle:进入Handler方法之后,返回modelAndView之前执行,应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
  • afterCompletion:执行Handler完成执行此方法,应用场景:统一异常处理,统一日志处理

为了更直观的了解SpringMVC拦截器的实现,我特写个demo,代码如下:

拦截器定义:

注意:com.shsxt.vo.User是一个简单的JavaBean,用于模拟用户登录而用。

package com.shsxt.interceptors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.shsxt.vo.User;
public class LoginInterceptor implements HandlerInterceptor{
	 /**
 	* 方法拦截前执行
 	*/
 	@Override
 	public boolean preHandle(HttpServletRequest request,HttpServletResponse response, 								Object handler) throws Exception {
 		User user= (User) request.getSession().getAttribute("user");
	 /**
	 * 判断 uri 是否包含路径
	 * 包含就放行
 	*/
 		if(request.getRequestURI().indexOf("userLogin.do")>-1){
 			return true;
 		} 
 	/**
	 * 判断 session user 是否为空
 	*/
 		if(null==user){
 			response.sendRedirect(request.getContextPath()+"/login.jsp");
 			return false;
 		}
 			return true; //继续执行 action
 	}
 	@Override
 	public void postHandle(HttpServletRequest request,HttpServletResponse response, 							Object handler,ModelAndView modelAndView) throws Exception {
 		System.out.println("Action 执行之后,生成视图之前执行!!"); 
 	}
 	/**
 	* 在方法执行后进行拦截
 	*/
 	@Override
 	public void afterCompletion(HttpServletRequest request,HttpServletResponse response, 								Object handler, Exception ex)throws Exception {
 
 	System.out.println("方法执行后进行拦截。。释放资源。。。");
 } 
}

UserController 类:

package com.shsxt.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.shsxt.vo.User;
/**
* 
* @author Administrator
* 模拟 用户操作
*/
@Controller
@RequestMapping("/user")
public class UserLoginController {
 
 	@RequestMapping("/userLogin")
 	public ModelAndView userLogin(HttpServletRequest request){
 		ModelAndView mv=new ModelAndView();
 		User user=new User();
 		user.setUserName("sxt");
 		user.setUserPwd("123456");
 		request.getSession().setAttribute("user", user);
 		mv.setViewName("success");
 		return mv; 
	 }
 	@RequestMapping("/addUser")
 	public ModelAndView addUser(){
 		System.out.println("添加用户记录。。。");
 		ModelAndView mv=new ModelAndView();
 		mv.setViewName("success");
 		return mv;
 	}
 	@RequestMapping("/delUser")
 	public ModelAndView delUser(){
 		ModelAndView mv=new ModelAndView();
 		mv.setViewName("success");
 		return mv;
 	}
 	@RequestMapping("/updateUser")
 	public ModelAndView updateUser(){
 		ModelAndView mv=new ModelAndView();
 		mv.setViewName("success");
 		return mv;
 	} 
}

XML配置:

<!-- 拦截所有请求 -->
<mvc:interceptors>
 <mvc:interceptor>
 <mvc:mapping path="/**" />
 <bean class="com.shsxt.interceptors.LoginInterceptor" />
 </mvc:interceptor>
</mvc:interceptors>

10、SpringMVC文件上传

​ ① 添加依赖与修改xml配置

<!--pom配置-->
<dependency>
<groupId>commons-fileupload</groupId>
 <artifactId>commons-fileupload</artifactId>
 <version>1.3.2</version>
</dependency>
<!---------------------------------------->
<!--xml配置-->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
 	<property name="maxUploadSize">
 		<value>104857600</value>
 	</property>
 	<property name="maxInMemorySize">
		 <value>4096</value>
     </property>
</bean>

②添加控制器

package com.shsxt.controller;
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FileController {
    
 @RequestMapping("/uploadFile")
    
 public ModelAndView uploadFile(HttpServletRequest request){
 
 	ModelAndView mv=new ModelAndView();
 	mv.setViewName("result");
 	MultipartHttpServletRequest mr=(MultipartHttpServletRequest) request;
 	MultipartFile multipartFile= mr.getFile("file");
 	String path=request.getSession().getServletContext().getRealPath("upload");
 		System.out.println(path);
 	if(null!=multipartFile&&!multipartFile.isEmpty()){
		 String fileName=multipartFile.getOriginalFilename();
		 try {
 			multipartFile.transferTo(new File(path,fileName));
 			mv.addObject("msg", "文件上传成功!");
		 } catch (Exception e) {
 			mv.addObject("msg", "上传失败!");
 			e.printStackTrace();
		 }
 		}
 		return mv;
 }
}

③ 准备前台表单

<form action="uploadFile.do" method="post" enctype="multipart/form-data">
 <input type="file" name="file" />
 <button type="submit"> 提交</button>
</form>

11、SpringMVC全局异常处理

​ SpringMVC对于异常处理提供支持,通过SpringMVC提供的全局异常处理机制,能够将所有的异常处理从各种处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。

SpringMVC提供的三种处理异常实现方式:

  1. 使用SpringMVC提供的简单异常处理器 SimpleMappingExceptionResolver
  2. 实现Spring的异常处理接口 HandlerExceptionResolver 自定义自己的异常处理器
  3. 使用@ExceptionHandler注解实现异常处理

具体实现代码(仅供参考):

第一种:配置SimpleMappingExceptionResolver对象

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
	<property name="defaultErrorView" value="error"></property>
	<property name="exceptionAttribute" value="ex"></property>
	<property name="exceptionMapping">
		<props>
			<prop key="com.shsxt.exception.BusinessException">error</prop>
			<prop key="com.shsxt.exception.ParamsException">error</prop>
		</props>
	</property>
</bean>

**注:**使用此方法进行异常处理,具有集成简单,有良好的扩展性,对已有代码没有入侵性等优点,但该方法仅能够获取到异常信息,若出现异常时,对需要获取异常以外的数据的情况不适用

第二种:实现HandlerExceptionReslover接口(推荐)

  
public class MyExceptionHandler implements HandlerExceptionResolver{ 
    
    @Override 
  	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse 										  response, Object handler, Exception ex){ 
        Map<String,Object> map=new HashMap<String, Object>(); 
        map.put("ex", ex); 
        ModelAndView mv=null; 
        if(ex instanceof ParamsException){ 
            return new ModelAndView("error_param", map); 
        } 
        if(ex instanceof BusinessException){ 
            return new ModelAndView("error_business", map); 
        } 
        return new ModelAndView("error", map); 
    } 
} 

注:使用实现此种异常处理器进行异常处理,比起上一种就是在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。

第三种:页面处理器继承 BaseController

public class BaseController { 
    @ExceptionHandler 
    public String exc(HttpServletRequest request,HttpServletResponse response,Exception 					 ex){ 
        request.setAttribute("ex", ex); 
        if(ex instanceof ParamsException){ 
            return "error_param"; 
        } 
        if(ex instanceof BusinessException){ 
            return "error_business"; 
        } 
        return "error"; 
    } 
} 

注:使用@ExceptionHandler 注解实现异常处理,具有集成简单、有扩展性好(只需要将要异常处理的Controller类继承于BaseController 即可)、不需要附加 Spring 配置等优点,但该方法对已有代码存在入侵性(需要修改已有代码,使相关类继承于 BaseController),在异常处理时不能获取除异常以外的数据。

未捕获的异常处理

修改 web.xml 文件,增加以下内容:

<!-- 出错页面定义 --> 
<error-page> 
    <exception-type>java.lang.Throwable</exception-type> 
    <location>/500.jsp</location> 
</error-page> 
<error-page> 
    <error-code>500</error-code> 
    <location>/500.jsp</location> 
</error-page> 
<error-page> 
    <error-code>404</error-code> 
    <location>/404.jsp</location> 
</error-page> 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值