欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring MVC框架

程序员文章站 2022-05-30 23:13:38
...

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响应用户

Spring MVC框架

总结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> 
相关标签: SSM