SpringMVC
一、Springmvc介绍
1、什么是Springmvc?
在Spring基础上 开发的框架 springMVC框架,是控制器框架 c层框架(Struts2也是C层框架)
本质:替换Struts2框架充当控制器
为了使Spring可插入MVC架构,SpringFrameWork在Spring基础上开发SpringMVC框架,从而在使用Spring进行WEB开发时可以选择使用Spring的SpringMVC框架作为web开发的控制器框架 。
MVC开发模式
1、M 模型层 实体+dao+Service 2、V 视图层 WebApp根下的页面 HTml+Jsp 3、C 控制层 Action/Controller Struts2/SpringMVC
2、SpringMvc好处
(1)SpringMvc基于Spring框架开发,能和Spring框架进行无缝整合 (2)SpringMvc的运行效率高于Struts2 (Spring对象默认单例模式,但是Struts2是多例模式,节约了运行时间) (3)SpringMvc支持注解开发,简单,快捷,注解式开发更高效
3、总结
Springmvc基于Spring开发的控制器框架
1、接收数据 2、调用业务 3、跳转页面
SpringMVC 轻量级,典型MVC框架 ,在整个MVC架构中充当控制器框架,相对于struts2框架,SpringMVC运行更快,其注解式开发更高效灵活 。
二、SpringMVC的组件解析
1、Struts2的执行流程
客户端请求:
1. 经过web.xml中的Struts2核心过滤器,将用户请求交给Struts2, 2. 先经过Struts.xml的package下的namespance 3、再去找action中的name加载Class下的Action类通过反射或者Class中的方法 4、在Action方法中接收数据,调用业务,跳转页面 5、返回到Result,加载跳转的页面 6、再次经过过滤器返回到客户端,将对应的结果返回给对应的用户
2、SpringMVC的执行流程
客户端请求:
1、先经过Web.xml 拦截请求 将请求转发(DispatcherServlet)给SpringMvc 2、处理器映射器(RequesMappingHandelMapping)解析请求路径 3、类上的RequestMapping(等价于Struts2中的namespace配置) 4、方法上的RequestMapping(等价于Struts2中的Action的name属性值) 5、接收前端的传过来的数据RequestMappingHandelAdapter 处理器适配器 负责接收解析数据 6、InternalResourceViewResolver 视图解析器 (解析返回值,当前跳转位置的前缀/和后缀.jsp) 返回结果: 前缀:/ 后缀:.jsp 结果: 前缀+返回的字符串+后缀
3、详细执行流程:
(1)用户发送请求至前端控制器DispatcherServlet。 (2)DispatcherServlet收到请求调用HandlerMapping处理器映射器。 (3)处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找), 生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。 (4)DispatcherServlet调用HandlerAdapter处理器适配器。 (5)HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。 (6)Controller执行完成返回ModelAndView。 (7)HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。 (8)DispatcherServlet将ModelAndView传给ViewReslover视图解析器。 (9)ViewReslover解析后返回具体View。 (10)DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户。
4、SpringMVC组件解析
(1)前端控制器:DispatcherServlet
用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的中心,由
它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。
(2)处理器映射器:HandlerMapping
HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的
映射方式,例如:配置文件方式,实现接口方式,注解方式等。
(3)处理器适配器:HandlerAdapter
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理
器进行执行。
(4)处理器:Handler
它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由
Handler 对具体的用户请求进行处理。
(5)视图解析器:View Resolver [rɪ’zɒlvə]
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
(6)视图:View
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面
三、第一个SpringMvc项目
1、引入相关依赖
<!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!--springmvc核心依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!--servlet-api--> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope>
2、编写springmvc配置文件(applicationContext.xml)
<!--开启注解扫描:component:组件[kəmˈpoʊnənt]--> <context:component-scan base-package="com.tjcu"></context:component-scan> <!--注册处理器映射器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean> <!--注册处理器适配器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean> <!--注册视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--prefix:[ˈpriːfɪks] 前缀--> <property name="prefix" value="/"></property> <!--suffix: [ˈsʌfɪks] 后缀--> <property name="suffix" value=".jsp"></property> </bean>
3、配置springmvc的核心Servlet
<!--负责转发请求--> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--指定mvc的配置文件位置和名字--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
注意 : 这里还要加载spring配置,通过在servlet写initparam标签,还是contextConfigLocation属性,value用来加载springmvc配置文件
Servlet默认单例,在第一个请求的时候创建,如果不想要写<init-param>,可以把配置文件放在Web-INF下,并命名为mvc-servlet.xml
4、创建控制器
//负责控制层组件对象创建 @Controller("userController") //类上的控制器映射器,相当于Struts2中的namespace @RequestMapping("user") public class UserController{ //方法上的控制器映射器,相当于Struts中的name @RequestMapping("queryAll") public String queryAll(){ System.out.println("查询到了很多数据"); //解析结果:前缀+返回值+后缀 return "index"; }
@Controller: 该注解用来类上标识这是一个控制器组件类并创建这个类实例
@RequestMapping:
修饰范围: 用在方法或者类上
注解作用: 用来指定类以及类中方法的请求路径
注解详解:
用在类上相当于struts2中namespace在访问类中方法必须先加入这个路径
用在方法上相当于action标签的name属性用来表示访问这个方法的路径
5.部署项目,启动项目测试
访问路径: http://localhost:8080/SpringMvc/user/queryAll
6、SpringMVC的开发步骤总结
①导入SpringMVC相关坐标(spring,servlet-api,spring-mvc等)
②配置SpringMVC核心控制器DispathcerServlet
③创建Controller类和视图页面
④使用注解配置Controller类中业务方法的映射地址
⑤配置SpringMVC核心文件 springmvc.xml(三大核心组件)
⑥客户端发起请求测试
四、SpringMVC中跳转方式
1、跳转方式
说明:跳转有两种=方式,一种forward ,一种**redirect ** [ˌriːdəˈrekt ]。
(1)Servlet跳转方式【底层】
#forward跳转, 一次请求,地址栏不变,可以使用request作用域传递数据, #redirect跳转多次, 地址栏改变,不能使用作用域
(2)Struts2中的跳转方式(区分跳转的目标资源类型)
#Action--->jsp forward[默认] type="dispatcher" redirect type="redirect" #Action--->Action forward type="chain" redirect type="redirectAction"
(3)springmvc跳转方式
# 1.Controller 跳转到JSP forward跳转到页面: 默认就是forward跳转 语法:return "业务逻辑名" 例子:return "showUer"---->/showUser.jsp redirect跳转到页面:使用SpringMVC提供rediret:关键字进行重定向页面跳转 语法:return "redirect:/index.jsp" 注意:使用redirect跳转页面不会经过视图解析器 # 2.Controller跳转到Controller forward跳转到Controller: 使用SpringMvc提供的关键字forward 语法:forward:/跳转类上@requestMapping的值/跳转类中方法@RequestMapping的值 例子:return "forward:test:/"; redirect跳转到Controller:使用SpringMvc提供的关键字redirect 语法:redirect:/跳转类上@requestMapping的值/跳转类中方法@RequestMapping的值
forward跳转到页面(.jsp)示意图:
redirect跳转到页面(.jsp)示意图:
forward方法: Controller层跳转到另外一个控制层(controller)示意图:
如果跳本类的一个控制器(controller)方法示意图:
redirect方法: Controller层跳转到另外一个控制层(controller)示意图:
2、跳转方法总结
五、SpringMVC中参数接收
接收参数语法说明:springmvc中使用控制器方法参数来收集客户端的请求参数,因此在接收请求参数时直接在需要控制器方法声明即可,springmvc可以自动根据指定类型完成类型的转换操作
1、接收零散类型的参数
如:八种基本类型+String+日期类型
Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配。并且能自动做类型
转换;
自动的类型转换是指从String向其他类型 的转换
(1)前端传递参数
#get方式传递参数 http://localhost:8080/SpringMvc/user/register? name=王恒杰&password=234&sex=true&birthday=1999/12/03&salary=20000 #post方式传递参数 <form action="${pageContext.request.contextPath}/user/register" method="posst"> 姓名:<input type="text" name="name"><br/> 密码:<input type="password" name="password"><br/> 性别:<input type="text" name="sex"><br/> 生日:<input type="text" name="birthday"><br/> 工资:<input type="text" name="salary"><br/> <input type="submit" value="提交"><br/> </form>
(2)后台Controller接收数据
//负责控制层组件对象创建 @Controller("userController") //类上的控制器映射器,相当于Struts2中的namespace @RequestMapping("user") public class UserController { @RequestMapping("register") public String register(String name, String password, Boolean sex, Date birthday, Double salary) { System.out.println("注册成功"); System.out.println("姓名" + name); System.out.println("密码" + password); System.out.println("性别" + sex); System.out.println("生日" + birthday); System.out.println("工资" + salary); return "index"; }
注意:springmvc在接收日期类型参数时日期格式必须为yyyy/MM/dd HH:mm:ss
2、接收对象类型参数
(1)前端传递参数
<form action="${pageContext.request.contextPath}/user/register" method="get"> 姓名:<input type="text" name="name"><br/> 密码:<input type="password" name="password"><br/> 性别:<input type="text" name="sex"><br/> 生日:<input type="text" name="birthday"><br/> 工资:<input type="text" name="salary"><br/> <input type="submit" value="提交"><br/> </form>
注意: 在接收对象类型参数时和struts2接收不同,springmvc直接根据传递参数名与对象中属性名一致自动封装对象
(2)后台Controller接收数据
实体类
public class User implements Serializable { private static final Long serialVersionUID=1L; private String name; private String password; private String sex; private String birthday; private String Salary;
控制器中接收前端数据
//负责控制层组件对象创建 @Controller("userController") //类上的控制器映射器,相当于Struts2中的namespace @RequestMapping("user") public class UserController{ @RequestMapping("register") public String register(User user){ System.out.println("注册成功"); System.out.println("姓名"+user.getName()); System.out.println("密码"+user.getPassword()); System.out.println("性别"+user.getSex()); System.out.println("生日"+user.getBirthday()); System.out.println("工资"+user.getSalary()); return "redirect:/index.jsp"; }
3、接收数组类型参数
(1)前端传递参数
(2)后台Controller接收数据
//负责控制层组件对象创建 @Controller("userController") //类上的控制器映射器,相当于Struts2中的namespace @RequestMapping("user") public class UserController{ @RequestMapping("register") public String register(User user, String[] hobby){ System.out.println("注册成功"); System.out.println("姓名:"+user.getName()); System.out.println("密码:"+user.getPassword()); System.out.println("性别:"+user.getSex()); System.out.println("生日:"+user.getBirthday()); System.out.println("工资:"+user.getSalary()); System.out.println("爱好:"); for (String s : hobby) { System.out.println(s); } return "redirect:/index.jsp"; }
4、SpringMVC接收参数中文乱码解决方案
(1)在使用post方式接收请求参数时出现中文乱码接收数据问题解决
<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>charset</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
(2)在使用set方式中文乱码问题
改tomcat的server.xml配置文件大概在50多行加上URIEncoding="UTF-8"
# 1.针对于GET方式中文乱码解决方案: <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
成功设置之后,接收到的数据就不会乱码了!
5、接收集合类型参数
说明:springmvc不支持直接将接收集合声明为控制器方法参数进行接收,如果要接收集合类型参数必须使用对象封装要接收接收类型才可以
(1)前端传递参数
<form action="${pageContext.request.contextPath}/user/register" method="post"> 姓名:<input type="text" name="name"><br/> 密码:<input type="password" name="password"><br/> 性别:<input type="text" name="sex"><br/> 生日:<input type="text" name="birthday"><br/> 工资:<input type="text" name="salary"><br/> <span> 爱好:</span> 吃饭:<input type="checkbox" name="hobby" value="吃饭"> 睡觉:<input type="checkbox" name="hobby" value="睡觉"> 爱杨福君:<input type="checkbox" name="hobby" value="爱杨福君"> 抽烟:<input type="checkbox" name="hobby" value="抽烟"> 喝酒:<input type="checkbox" name="hobby" value="喝酒"> 烫头发:<input type="checkbox" name="hobby" value=" 烫头发"> <br/> <span> 擅长技术:</span><br> <input type="checkbox" name="lists" value="python">python<br> <input type="checkbox" name="lists" value="java">java<br> <input type="checkbox" name="lists" value="c++"> c++<br> <input type="checkbox" name="lists" value="linux">linux<br> <input type="checkbox" name="lists" value="计算机网络">计算机网络<br> <input type="checkbox" name="lists" value="go">go<br> <br/> <input type="submit" value="提交"><br/> </form>
(2)后台Controller接口
// 1.封装接收集合类型对象---->在spring mvc中用来接收集合类型参数 class Collection{ private List<String> lists; public List<String> getLists() { return lists; } public void setLists(List<String> lists) { this.lists = lists; } } // 2.控制器中接收集合类型参数 //负责控制层组件对象创建 @Controller("userController") //类上的控制器映射器,相当于Struts2中的namespace @RequestMapping("user") public class UserController{ @RequestMapping("register") public String register(User user, String[] hobby,Collection collection){ System.out.println("注册成功"); System.out.println("姓名:"+user.getName()); System.out.println("密码:"+user.getPassword()); System.out.println("性别:"+user.getSex()); System.out.println("生日:"+user.getBirthday()); System.out.println("工资:"+user.getSalary()); System.out.println("爱好:"); for (String s : hobby) { System.out.print(s); } //换行 System.out.println(); System.out.println("个人技能"); for (String list : collection.getLists()) { System.out.print(list+" ,"); } return "redirect:/index.jsp"; }
(3)使用Lambda优化接收集合和数组数据
报错原因:使用Lambda需要JDK8版本及以上
优化后ontroller接收数据代码
class Collection{ private List<String> lists; public List<String> getLists() { return lists; } public void setLists(List<String> lists) { this.lists = lists; } } //负责控制层组件对象创建 @Controller("userController") //类上的控制器映射器,相当于Struts2中的namespace @RequestMapping("user") public class UserController{ @RequestMapping("register") public String register(User user, String[] hobby,Collection collection){ System.out.println("注册成功"); System.out.println("姓名:"+user.getName()); System.out.println("密码:"+user.getPassword()); System.out.println("性别:"+user.getSex()); System.out.println("生日:"+user.getBirthday()); System.out.println("工资:"+user.getSalary()); //优化版本,使用Lambda表达式接收集合和数组 System.out.println("爱好:"); Arrays.asList(hobby).forEach(item -> System.out.println(item)); //换行 System.out.println(); System.out.println("个人技能"); collection.getLists().forEach(name-> System.out.println(name)); return "redirect:/index.jsp"; } }
六、SpringMVC中数据传递机制
1.数据传递机制
# 1.数据怎么存 Servlet 作用域 Struts2 作用域 SpringMVC 作用域 # 2.数据怎么取 Servlet EL表达式 Struts2 EL表达式 SpringMVC EL表达式 # 3.数据怎么展示 Servlet JSTL标签 Struts2 JSTl标签 SpringMVC JSTl标签
2.使用forward跳转传递数据
# 1.使用servlet中原始的request作用域传递数据 request.setAttribute("key",value); # 2.使用是springmvc中封装的Model和ModelMap对象(底层对request作用域封装) model.addAttribute(key,value); modelMap.addAttribute(key,value);
(1)使用servlet中原始的request作用域传递数据
#如何获取springmvc控制器方法中获取request对象,response对象? 注意:直接将request,response对象作为控制器方法参数声明即可获取
controller层使用request传递数据
//方法上的控制器映射器,相当于Struts中的name @RequestMapping("queryAll") public String queryAll(HttpServletRequest request, HttpServletResponse response) { System.out.println("SpringMvc使用Request数据"); request.setAttribute("name","王恒杰"); //解析结果:前缀+返回值+后缀 return "index"; }
客户端使用EL接收数据
<%@page pageEncoding="UTF-8" isELIgnored="false" %> <html> <body> <h2>用户数据进行展示</h2> SpringMVC使用request传递的数据,jsp使用EL接收数据:${requestScope.name} </body> </html>
(2)使用Model对象保存数据
3.使用Redirect跳转传递数据
# 1.使用地址栏进行数据传递 url?name=zhangsan&age=21 # 2.使用session作用域 session.setAttribute(key,value); session.getAttribute(key);
//方法上的控制器映射器,相当于Struts中的name @RequestMapping("queryAll") public String queryAll(HttpServletRequest request, HttpServletResponse response) { System.out.println("SpringMvc使用Request数据"); request.setAttribute("name","王恒杰"); //解析结果:前缀+返回值+后缀 return "index"; }
客户端使用EL接收数据
<%@page pageEncoding="UTF-8" isELIgnored="false" %> <html> <body> <h2>用户数据进行展示</h2> SpringMVC使用request传递的数据,jsp使用EL接收数据:${requestScope.name} </body> </html>
(2)使用Model对象保存数据
3.使用Redirect跳转传递数据