SpringMVC第一天---简述三层架构+MVC+SpringMVC的简介+参数绑定+参数乱码+自定义类型转换器+常用的注解

一、系统标准三层架构

主流的开发架构一般有两种,一种是 C/S 架构,即客户端/服务器,另一种是 B/S 架构,也就是浏览器/服务器。Java非常适合用于B/S架构的开发,在B/S 架构中,系统被分为标准的三层架构,包括:表现层、业务层、持久层。三层架构各司其职,协调运转,构成了一个完整的网站架构,如下图:

在这里插入图片描述

1.1Web 表现层

负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层, web 需要接收 http 请求,完成 http 响应,表现层包括展示层和控制层:控制层负责接收请求,展示层负责结果的展示。它的设计一般都使用 MVC 模型

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

1.2 Service业务层

负责业务逻辑处理,和我们开发项目的需求息息相关。 web 层依赖业务层,但是业务层不依赖 web 层。同时业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性,那么应该在业务层进行事务控制。

1.3 Dao持久层

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

二、MVC模型

MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,
是一种用于设计创建 Web 应用程序表现层的模式。 MVC 中每个部分各司其职:

Model(模型)

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

View(视图)

通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。通常视图是依据模型数据创建的。

Controller(控制器)

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

三、SpringMVC

3.1 什么是SpringMVC?

SpringMVC 就是Web表现层的一种框架,是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,随着 Spring3.0 的发布, SpringMVC全面超越 Struts2,成为最优秀的 MVC 框架。
它通过一套注解(@Controller),让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful 编程风格的请求。

3.2 SpringMVC在三层结构中的位置

下面引用Spring官网中的一张图来描述SpringMVC在三层架构中的位置。

在这里插入图片描述

3.3 对比分析SpringMVC和Struts2

共同点

  • 它们都是表现层框架,都是基于 MVC 模型编写的。
  • 它们的底层都离不开原始 ServletAPI。
  • 它们处理请求的机制都是一个核心控制器。

区别

  • Spring MVC 的入口是 Servlet(即前端控制器), 而 Struts2 是 Filter
  • Spring MVC 是基于方法设计的,而 Struts2 是基于类, Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
  • Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
    (JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验了。 )
  • Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 html 执行效率高。

四、参数绑定

4.1 绑定机制

在web层中传给业务层的数据都是基于 key=value 形式的。SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的

示例

JSP代码

<a  href="hello/testId?id=zhangsa">点击发送id到业务层</a>

业务层代码

@Controller
@RequestMapping(path = "/hello")
public class HelloController {
    @RequestMapping(path = "/testId")
    public String sayHello(String id){
        System.out.println(id);
        return "success";
    }
}

必须保证超链接中的属性名和RequestMap对应的方法参数名保持一致

4.2 支持绑定的数据类型
  • 基本类型参数
    包括基本类型和 String 类型

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

  • 数组和集合类型参数:
    包括 List 结构和 Map 结构的集合(包括数组)
    SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。

4.3 使用要求
  • 如果是基本类型或者 String 类型
    要求我们的参数名称必须和控制器中方法的形参名称保持一致。 (严格区分大小写)

  • 如果是 POJO 类型,或者它的关联对象
    要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。

  • 如果是集合类型,有两种方式
    第一种:
    要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。给 List 集合中的元素赋值, 使用下标。给 Map 集合中的元素赋值, 使用键值对。

    第二种:
    接收的请求参数是 json 格式数据。需要借助一个注解实现。

前端代码

<form action="account/updateAccount" method="get">
        ID:<input type="text" name="uid"><br/>
        name:<input type="text" name="username"><br/>
        
    <%--测试数组类型--%>
    province:<input type="text" name="address.province"><br/>
    city:<input type="text" name="address.city"><br/>
    
    <%--测试List集合类型--%>
    account1:<input type="text" name="accounts[0].name">
    money:<input type="text" name="account[0].money"><br/>
    account2:<input type="text" name="account[1].name" >
    money:<input type="text" name="account[1].money" ><br/>
    
    <%--测试Map集合类型--%>
    account3:<input type="text" name="accountMap['one'].name" >
    money:<input type="text" name="accountMap['one'].money" ><br/>
    account4:<input type="text" name="accountMap['two'].name" >
    money:<input type="text" name="accountMap['two'].money" ><br/>
    <input type="submit" value="提交">
</form>

控制器代码

@Controller
@RequestMapping("/account")
public class AccountController {
    @RequestMapping("/updateAccount")
    public String updateAccount(User user){
        System.out.println("执行成功"+user);
        return "success";
    }
}
请求参数乱码问题

需要在web.xml中配置一个拦截器,如下:

 <!--配置中文乱码解析器-->
<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>
自定义类型转换器

1.自定义一个类实现Converter 接口

public class StringToDate implements Converter<String,Date> {


@Override
public Date convert(String s) {
        if (s==null){
            throw new RuntimeException("请传入正确参数");
        }
        DateFormat format=new SimpleDateFormat("yyyy-MM-dd");
        try{
            return format.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException("类型转换失败");
        }
    }
}

2.在 spring 配置文件中配置类型转换器

<!--配置类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.gzgs.utils.StringToDate"/>
        </set>
    </property>
</bean>

3.在 annotation-driven 标签中引用配置的类型转换服务

 <!-- 开启注解转换器支持-->
<mvc:annotation-driven conversion-service="conversionService"/>

四、常用注解

4.1@RequestParam

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

属性

  • value: 请求参数中的名称。
  • required:请求参数中是否必须提供此参数。 默认值: true。表示必须提供,如果不提供将报错。

示例

jsp 中的代码:

<!-- requestParams 注解的使用 -->
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a>

Controller代码:

@RequestMapping("/useRequestParam")
public String useRequestParam(@RequestParam("name")String username,
@RequestParam(value="age",required=false)Integer age){
	System.out.println(username+","+age);
	return "success";
}
4.2 @RequestBody

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

属性

  • required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值
    为 false, get 请求得到是 null。

示例

jsp 中的代码:

<!-- post 请求 jsp 代码 -->
<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>


<!--get 请求 jsp 代码:-->
<a href="springmvc/useRequestBody?body=test">requestBody 注解 get 请求</a>

Controller代码:

@RequestMapping("/useRequestBody")
public String useRequestBody(@RequestBody(required=false) String body){
	System.out.println(body);
	return "success";
}
4.3 @PathVaribale

作用:用于绑定 url 中的占位符。 例如:请求 url 中 /delete/{id}, 这个{id}就是 url 占位符。url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。

属性

  • value: 用于指定 url 中占位符名称。
  • required:是否必须提供占位符。

示例

jsp 中的代码:

<a href="springmvc/usePathVariable/100">pathVariable 注解</a>

Controller代码:

@RequestMapping("/usePathVariable/{id}")
public String usePathVariable(@PathVariable("id") Integer id){
	System.out.println(id);
	return "success";
}
4.4 @RequestHeader

作用:用于获取请求消息头。(不怎么用)

属性

  • value:提供消息头名称
  • required:是否必须有此消息头

示例

jsp 中的代码:

<a href="springmvc/useRequestHeader">获取请求消息头</a>

Controller代码:

@RequestMapping("/useRequestHeader")
public String useRequestHeader(@RequestHeader(value="Accept-Language",
required=false)String requestHeader){
	System.out.println(requestHeader);
	return "success";
}
4.5 @CookieValue

作用:用于把指定 cookie 名称的值传入控制器方法参数。

属性

  • value:指定 cookie 的名称。
  • required:是否必须有此 cookie。

示例

jsp 中的代码:

<a href="springmvc/useCookieValue">绑定 cookie 的值</a>

Controller代码:

@RequestMapping("/useCookieValue")
public String useCookieValue(@CookieValue(value="JSESSIONID",required=false)String cookieValue){
	System.out.println(cookieValue);
	return "success";
}
4.6 @ModelAttribute

作用

该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。

属性

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

示例

jsp 中的代码:

<a href="springmvc/testModelAttribute?username=test">测试 modelattribute</a>

Controller代码:

/**
* 被 ModelAttribute 修饰的方法
* @param user
*/
@ModelAttribute
public void showModel(User user) {
	System.out.println("执行了 showModel 方法"+user.getUsername());
}
/**
* 接收请求的方法
* @param user
* @return
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
	System.out.println("执行了控制器的方法"+user.getUsername());
	return "success";
}
4.7 @SessionAttribute

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

属性

  • value:用于指定存入的属性名称
  • type:用于指定存入的数据类型

示例

jsp 中的代码:

<!-- SessionAttribute 注解的使用 -->
<a href="springmvc/testPut">存入 SessionAttribute</a>
<hr/>
<a href="springmvc/testGet">取出 SessionAttribute</a>
<hr/>
<a href="springmvc/testClean">清除 SessionAttribute</a>

Controller代码:

@Controller("sessionAttributeController")
@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";
	}
	@RequestMapping("/testGet")
	public String testGet(ModelMap model){
		System.out.println(model.get("username")+";"+model.get("password")+";"+model.get("a
		ge"));
		return "success";
	}
	@RequestMapping("/testClean")
	public String complete(SessionStatus sessionStatus){
		sessionStatus.setComplete();
		return "success";
	}
}
学习代码:https://download.csdn.net/download/weixin_45680962/12609182
本博客纯属个人学习笔记,学习资源来自黑马训练营,如有错误,感激指正
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在刚刚步入“多层结构”Web应用程序开发的时候,我阅读过几篇关于“asp.net三层结构开发”的文章。但其多半都是对PetShop3.0和Duwamish7的局部剖析或者是学习笔记。对“三层结构”通体分析的学术文章几乎没有。 2005年2月11日,Bincess BBS彬月论坛开始试运行。不久之后,我写了一篇题目为《浅谈“三层结构”原理与用意》的文章。旧版文章以彬月论坛程序中的部分代码举例,通过全局视角阐述了什么是“三层结构”的开发模式?为什么要这样做?怎样做?……而在这篇文章的新作中,配合这篇文章我写了7个程序实例(TraceLWord1~TraceLWord7留言板)以帮助读者理解“三层结构”应用程序。这些程序示例可以在随带的CodePackage目录中找到——   对于那些有丰富经验的Web应用程序开发人员,他们认为文章写的通俗易懂,很值得一读。可是对于asp.net初学者,特别是没有任何开发经验的人,文章阅读起来就感到非常困难,不知文章所云。甚至有些读者对“三层结构”的认识更模糊了……   关于“多层结构”开发模式,存在这样一种争议:一部分学者认为“多层结构”与“面向对象的程序设计思想”有着非常紧密的联系。而另外一部分学者却认为二者之间并无直接联系。写作这篇文章并不是要终结这种争议,其行文目的是希望读者能够明白:在使用asp.net进行Web应用程序开发时,实现“多层结构”开发模式的方法、原理及用意。要顺利的阅读这篇文章,希望读者能对“面向对象的程序设计思想”有一定深度的认识,最好能懂一些“设计模式”的知识。如果你并不了解前面这些,那么这篇文章可能并不适合你现在阅读。不过,无论这篇文章面对的读者是谁,我都会尽量将文章写好。我希望这篇文章能成为学习“三层结构”设计思想的经典文章!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空圆小生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值