SpringMVC框架

SpringMVC是什么

SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架 ,属于 SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 里面。

三层架构

在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。

表现层

也就是我们常说的 web 层。它负责接收客户端请求,向客户端响应结果,通常客户端使用 http 协议请求web 层,web 需要接收 http 请求,完成 http 响应。

表现层包括展示层和控制层:控制层负责接收请求,展示层负责结果的展示。

表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。

表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系)

业务层

也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。

业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也就是我们说的,事务应该放到业务层来控制)

持久层:

也就是我们是常说的 dao 层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体, 数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库交互,对数据库表进行曾删改查的。

MVC模型

MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种用于设计创建 Web 应用程序表现层的模式

Model(模型)

通常指的就是我们的数据模型。作用一般情况下用于封装数据。

View(视图)

通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。

通常视图是依据模型数据创建的。

Controller(控制器)

是应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。

SpringMVC在三层架构中位置

位于三层架构中的表现层,使用MVC模型设计

简单入门案例对springMVC的实现的流程图

请求参数绑定

SpringMVC绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定;SpringMVC绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。

支持的请求类型

  • 基本类型参数:基本类型和String类型

  • POJO类型参数:包括实体类以及关联的实体类

  • 数据和集合类型参数:包括List结构和Map结构的集合

使用要求

基本类型或String类型

要求我们的参数名称必须和控制器中方法的形参名称保持一致(严格区分大小写)

POJO类或者它的关联对象

要求表单中参数名称和POJO类的属性名称保持一致。并且控制器的方法的参数类型是POJO类型

实体类代码

jsp请求代码,属性名称和实体类属性一致

数组和集合类型参数

第一种:

要求集合类型的请求参数必须在POJO中,在表单中请求参数名称要和POJO中集合属性名称相同。

给List集合中的元素赋值,使用下标。

给Map集合中的元素赋值,使用键值对。

实体类代码

JSP代码

控制器代码

第二种:

接受的请求参数是json格式数据,需要借助一个主机实现

注意:实现一些数据类型自动转换,内置转换器全都在:org.springframework.core.convert.support包下

使用ServletAPI对象作为方法参数

SpringMVC还支持使用原始ServletAPI对象作为控制器方法的参数。支持原始ServletAPI对象有:

常用注解

@RequestParam

作用:把请求中指定名称的参数给控制器中的形参赋值

属性

​ value:请求参数中的名称

​ required:请求参数中是否必须提供此参数。默认值:true,表示必须提供,不提供将报错

jsp 中的代码:
<!-- requestParams 注解的使用 -->
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a>
//控制器代码
@RequestMapping("/useRequestParam")
public String useRequestParam(@RequestParam("name") String username,@RequestParam(value="age",required=false)Integer age){
	System.out.println(username+","+age);
	return "success";
}

@RequestBody

作用:用于获取请求体内容。直接使用得到的是key=value&key=value...结构的数据;get请求方式不适用

属性

​ required:是否必须有请求体。默认值是:true。当取值为true时,get请求方式会报错。

<!-- request body 注解 -->
<form action="springmvc/useRequestBody" method="post">
	用户名称:<input type="text" name="username" ><br/>
	用户密码:<input type="password" name="password" ><br/>
	用户年龄:<input type="text" name="age" ><br/>
	<input type="submit" value="保存">
</form>
//控制器代码
@RequestMapping("/useRequestBody")
public String useRequestBody(@RequestBody(required=false) String body){
	System.out.println(body);
	return "success";
}

@PathVaribale

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

属性

​ value:用于指定url中占位符名称

​ required:是否必须提供占位符

使用示例

<!--jsp 代码: -->
<!-- PathVariable 注解 -->
<a href="springmvc/usePathVariable/100">pathVariable 注解</a>
//控制器代码
@RequestMapping("/usePathVariable/{id}")
public String usePathVariable(@PathVariable("id") Integer id){
	System.out.println(id);
	return "success";
}

@ModelAttribute

作用:该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。

出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。

出现在参数上,获取指定的数据给参数赋值。

属性:

value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。

应用场景:我们在编辑一个用户时, 用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。

@ModelAttribute
public void showModel(User user) {
	System.out.println("执行了 showModel 方法"+user.getUsername());
}

@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
	System.out.println("执行了控制器的方法"+user.getUsername());
	return "success";
}

//执行了 showModel 方法
//执行了控制器的方法

@SessionAttribute

作用:

用于多次执行控制器方法间的参数共享。

属性:

value:用于指定存入的属性名称

type:用于指定存入的数据类型。

示例:

@RequestMapping("/springmvc")
@SessionAttributes(value ={"username","password"},types={Integer.class})
public class SessionAttributeController {
  	@RequestMapping("/testPut")
		public String testPut(Model model){
		model.addAttribute("username", "泰斯特");
		model.addAttribute("password","123456");
		model.addAttribute("age", 31);
		//跳转之前将数据保存到 username、password 和 age 中,因为注解@SessionAttribute 中有这几个参数
	return "success";
}
  
//可直接获取SessionAttribute域中的对象值
@RequestMapping("/testGet")
public String testGet(ModelMap model){
 System.out.println(model.get("username")+";"+model.get("password")+";"+model.get("age"));

@ResponseBody

作用:使用@ResponseBody 注解实现将 controller 方法返回对象转换为 json 响应给客户端。

将返回的Account对象转变为json数据响应给客户端

@RequestMapping("/testResponseJson")
public @ResponseBody Account testResponseJson(@RequestBody Account account) {
	System.out.println("异步请求:"+account);
	return account;
}

响应数据和结果视图

返回值类型

字符串

controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。

视图解析器配置,跳转到success页面

@RequestMapping("/testReturnString")
public String testReturnString() {
	System.out.println("AccountController 的 testReturnString 方法执行了。。。。");
	return "success";
}
<!-- 配置视图解析器 -->

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
	<property name="prefix" value="/WEB-INF/pages/"></property>
	<property name="suffix" value=".jsp"></property>
</bean>

void

在 controller 方法形参上可以定义 request 和 response,使用 request 或 response 指定响应结果

@RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request,HttpServletResponse response)throws Exception {
	//1、使用 request 转向页面,如下:
  request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
  //2、也可以通过 response 页面重定向:
  response.sendRedirect("testRetrunString")
}

ModelAndView

ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。

该对象中有两个方法:

addObject(String attributeName,Object attributeValue)添加模型到该对象中

页面上可用el表达式取值 ${attributeName}

public ModelAndView addObject(String attributeName,Object attributeValue){
  getModelMap().addAttribute(attributeName,attributeValue);
  return this;
}

setViewName(@Nullable String viewName)

用于设置逻辑视图名称,视图解析器会根据名称前往指定的视图

public void setViewName(@Nullable String viewName){
  this.view = viewName;
}

示例代码:

@RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView(){
  ModelAndView mv = new ModelAndView();
  mv.addObject("username","small_fish"); //键值对绑定
  mv.setViewName("success"); //设置逻辑视图,根据名称跳转到指定视图
  return mv;
}

SpringMVC文件上传

传统方式上传原理

编写jsp文件

<form action="/fileUpload" method="post" enctype="multipart/form-data">
	名称:<input type="text" name="picname"/>  
  图片:<input type="file" name="uploadFile"/><br/>
  <input type="submit" value="上传"/>
</form>

编写文件上传控制器

@Controller("fileUploadController")
public class FileUploadController {
	@RequestMapping("/fileUpload")
  public String testResponseJson(String uploadFile,HttpServletRequest request) throws Exception{
    //定义文件名
		String fileName = "";
		//1.获取原始文件名
		String uploadFileName = uploadFile.getOriginalFilename();
		//2.截取文件扩展名
    String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1,uploadFileName.length());
    //3.把文件加上随机数,防止文件重复
    String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
    //4.判断是否输入了文件名
    if(!StringUtils.isEmpty(picname)) {
			fileName = uuid+"_"+picname+"."+extendName;
		}else {
			fileName = uuid+"_"+uploadFileName;
		}
		System.out.println(fileName);

		//5.获取文件路径
    ServletContext context = request.getServletContext();
    String basePath = context.getRealPath("/uploads");
    //6.解决同一文件夹中文件过多问题
    String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    //7.判断路径是否存在
    File file = new File(basePath+"/"+datePath);
    if(!file.exists()) {
			file.mkdirs();
		}
    //8.使用 MulitpartFile 接口中方法,把上传的文件写到指定位置
    uploadFile.transferTo(new File(file,fileName));
    return "success";
  }
}


配置文件解析器

<!--配置文件上传解析器 -->
<bean id="multipartResolver" <!-- id 的值是固定的-->
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
  <!-- 设置上传文件的最大尺寸为 5MB -->
  <property name="maxUploadSize">
  <value>5242880</value>
  </property>
</bean>

文件上传的解析器 id 是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不光是文件,其他字段也将无法绑定)

SpringMVC异步文件上传

//5.创建 sun 公司提供的 jersey 包中的 Client 对象

Client client = Client.create();

//6.指定上传文件的地址,该地址是 web 路径

WebResource resource = client.resource(FILESERVERURL+fileName);

//7.实现上传

String result = resource.put(String.class,uploadFile.getBytes());

System.out.println(result);

return "success";

SpringMVC中的异常处理

SpringMVC拦截器

拦截器的作用

Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。拦截器 它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦

我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

拦截器流程图

请求先经过拦截器1,运行代码1,若返回值为true,继续转到拦截器2

拦截器2,运行代码1,若返回值为true,跳转运行controller层

运行controller层完成后,返回拦截器2,运行代码2,继续返回拦截器1,运行代码1

拦截器配置

Springmvc.xml

<!--配置拦截器-->
    <mvc:interceptors>
        <!--配置拦截器-->
        <mvc:interceptor>
            <!--要拦截的具体的方法-->
            <mvc:mapping path="/user/*"/>
            <!--不要拦截的方法
            <mvc:exclude-mapping path=""/>
            -->
            <!--配置拦截器对象-->
            <bean class="com.tyut.interceptor.MyInterceptor1" />
        </mvc:interceptor>

        <!--配置第二个拦截器-->
        <mvc:interceptor>
            <!--要拦截的具体的方法-->
            <mvc:mapping path="/**"/>
            <!--不要拦截的方法
            <mvc:exclude-mapping path=""/>
            -->
            <!--配置拦截器对象-->
            <bean class="com.tyut.interceptor.MyInterceptor2" />
        </mvc:interceptor>
    </mvc:interceptors>

自定义拦截器 MyInterceptor1 implements HandlerInterceptor

/**
 * 自定义拦截器
 */
public class MyInterceptor1 implements HandlerInterceptor{

    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false不放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了...前1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp执行之前
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1执行了...后1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }

    /**
     * success.jsp页面执行后,该方法会执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最后1111");
    }

}
posted @ 2022-09-06 17:28  lalalaxiaoyuren  阅读(24)  评论(0编辑  收藏  举报