1.Spring入门
-
1.1 回顾MVC架构
- MVC是一种架构模型,本身没有什么功能,只是让我们的项目结构更加合理,流程控制更加清晰,一般包含三个组件:
-
Model(模型):数据模型,用于提供要展示的数据。一般包含数据和行为(也就是业务),在JavaWEB中,数据和业务往往是分离开的。
-
View(视图):负责对模型数据进行展示,例如我们看到的网页。概念比较广泛,可以是:html、JSP、excel、Word、PDF、json、XML等
-
Controller(控制器):接收用户请求,委托给模型做处理,处理完毕返回数据,再交给视图做渲染,相当于调度员工作
-
- MVC是一种架构模型,本身没有什么功能,只是让我们的项目结构更加合理,流程控制更加清晰,一般包含三个组件:
-
1.2 什么是SpringMVC?
-
SpringMVC是Spring架构中的一部分:
- Spring Web MVC是一种基于Java的,实现了Web MVC设计模式的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,采用了松散耦合可插拔组件结构,比其它MVC框架更具扩展性和灵活性。
-
可以让我们实现:
- 进行更简洁的Web层的开发;
- 天生与Spring框架集成(如IoC容器、AOP等);
- 提供强大的约定大于配置的契约式编程支持;
- 支持灵活的URL到页面控制器的映射;
- 非常容易与其他视图技术集成,如Velocity、FreeMarker等等,因为模型数据不放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用);
- 非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
- 支持Restful风格。
-
SpringMVC在架构设计、扩展性、灵活性方面已经全面超越了Struts、WebWork等MVC框架,从原来的追赶着一跃成为MVC的领跑者!Springmvc处理流程 如下图所示:
-
2.创建springMVC项目
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- servlet -->
<!-- j2ee -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- springframework -->
<dependency>
<!-- context中有其他的依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<!-- mysql数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 数据库 连接池 德鲁伊 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- orm spring对数据库模块 尽量保证spring模块版本一致,这里都为4.2.6 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<!-- mvc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
</dependencies>
-
2.1 加入配置文件
- spring-dao.xml 用于配置数据库相关信息
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com.yiran.mvc.dao.impl"/> <aop:aspectj-autoproxy/> <!-- Spring的事务管理 spring配置的数据源dataSource --> <!-- 引入外部属性配置文件--> <context:property-placeholder location="classpath:jdbc.properties" /> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本属性 url、user、password --> <property name="driverClassName" value="${jdbc.driverClass}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 配置监控统计拦截的filters --> <property name="filters" value="stat"/> <!-- 配置初始化大小、最小、最大 --> <property name="maxActive" value="20"/> <property name="initialSize" value="1"/> <property name="minIdle" value="1"/> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="60000"/> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000"/> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000"/> <property name="testWhileIdle" value="true"/> <property name="testOnBorrow" value="false"/> <property name="testOnReturn" value="false"/> <!-- 打开PSCache,并且指定每个连接上PSCache的大小 --> <property name="poolPreparedStatements" value="true"/> <property name="maxOpenPreparedStatements" value="20"/> </bean> <!-- Spring为每一个持久化技术都提供了支持类。Spring对不同持久化技术的支持,Spring为各种支持的持久化技术,都提供了简单操作的模板和回调 JdbcTemplate - 简化 jdbc编程 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 依赖于上面配置的德鲁伊连接池 --> <property name="dataSource" ref="dataSource" /> </bean> </beans>
- spring-service.xml 用于配置事务
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="com.yiran.mvc.service.impl"/> <!-- 第一步:定义具体的平台事务管理器(DataSource事务管理器) 两个xml目前互不关联,在test中引入两个即可 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 第二步:定义通知,通知中要处理的就是事务 --> <!-- 这里的transaction-manager关联上面的平台事务管理器 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 配置事务的属性定义 --> <tx:attributes> <!-- 配置具体的方法的事务属性 isolation 事务的隔离级别,默认是按数据库的隔离级别来 propagation 事务的传播行为,默认是同一个事务 timeout="-1": 事务的超时时间,默认值使用数据库的超时时间。 read-only="false": 事务是否只读,默认可读写。 rollback-for: 遇到哪些异常就回滚,其他的都不回滚 no-rollback-for: 遇到哪些异常不回滚,其他的都回滚。和上面互斥的 --> <!-- <tx:method name="transfer*" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false" /> --> <tx:method name="transfer*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <!-- select 查询 - 设置 是否只读,默认为false,因为这里是查询,所以改为只读 read-only="true" --> <tx:method name="find*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 第三步:配置切入点,让通知关联切入点,即事务控制业务层的方法 --> <aop:config> <!-- 切入点 --> <aop:pointcut expression="execution(* com.yiran.mvc.service.*.*(..))" id="txPointcut"/> <!-- 切面 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config> </beans>
- spring-web.xml 用于配置mvc注解驱动、视图解析器等
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.yiran.mvc.web.action"/> <!-- 注解驱动 直接配置处理器映射器和处理器适配器比较麻烦,可以使用注解驱动来加载。 SpringMVC使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter --> <mvc:annotation-driven/> <!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" --> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置逻辑视图的前缀 --> <property name="prefix" value="/WEB-INF/view/" /> <!-- 配置逻辑视图的后缀 --> <property name="suffix" value=".jsp" /> </bean> </beans>
-
2.3 配置前端控制器DispatcherServlet,在web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<!-- 配置springMVC前端中央控制器DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定springMVC的web配置文件
springMVC的配置文件的默认路径为/WEB-INF/${servlet-name}-servlet.xml
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-web.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<!-- 这里的servlet-name要与上面servlet中定义的name相同 -->
<servlet-name>springmvc</servlet-name>
<!-- 设置所有以.action结尾的请求进入springMVC -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!-- 使用监听器加载spring配置文件 -连接池、事务等 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-service.xml,classpath:spring-dao.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
3.Springmvc架构
-
3.1 框架结构
-
框架结构如下图:
-
3.2 架构流程
-
1、用户发送请求至前端控制器DispatcherServlet
-
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
-
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
-
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
-
5、执行处理器(Controller,也叫后端控制器)。
-
6、Controller执行完成返回ModelAndView (根据url调用具体的控制器handler-执行具体的方法 – 返回ModelAndView)
-
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
-
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
-
9、ViewReslover解析后返回具体View
-
10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
-
11、DispatcherServlet响应用户
-
-
3.3 组件说明
-
以下组件通常使用框架提供实现:
-
DispatcherServlet:前端控制器
- 用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
-
HandlerMapping:处理器映射器
- HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
-
Handler:处理器
- Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。 XxxAction – @Controller
-
HandlAdapter:处理器适配器
- 通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
-
ViewResolver:视图解析器
- View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
-
View:视图
- springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
- 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
-
说明:
- 在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。
- 需要用户开发的组件有handler、view
-
-
3.4 组件扫描器
- 使用组件扫描器省去在spring容器配置每个Controller类的繁琐。
- 使用context:component-scan自动扫描标记@Controller的控制器类,
- 在spring-web.xml配置文件中配置如下
<!-- 配置controller扫描包,多个包之间用,分隔 --> <context:component-scan base-package="com.yiran.mvc.web.action"/>
-
3.5 注解映射器和适配器
-
3.5.1 配置处理器映射器
- 注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射。根据@ResquestMapping定义的url匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。
- HandlerMethod对象中封装url对应的方法Method。
- 从spring3.1版本开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射。
- 在spring-web.xml配置文件中配置如下
<!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- 注解描述:
- @RequestMapping:定义请求url到处理器功能方法的映射
-
3.5.2 配置处理器适配器
- 注解式处理器适配器,对标记@ResquestMapping的方法进行适配。
- 从spring3.1版本开始,废除了AnnotationMethodHandlerAdapter的使用,推荐使用RequestMappingHandlerAdapter完成注解式处理器适配。
- 在spring-web.xml配置文件中配置如下
<!-- 配置处理器适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
-
3.5.3 注解驱动
- 直接配置处理器映射器和处理器适配器比较麻烦,可以使用注解驱动来加载。
- SpringMVC使用mvc:annotation-driven自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter
- 可以在springmvc.xml配置文件中使用mvc:annotation-driven替代注解处理器和适配器的配置。
<!-- 注解驱动 --> <mvc:annotation-driven />
-
-
3.6 视图解析器
- 视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,这个视图解析器支持JSP视图解析
- 在spring-web.xml配置文件中配置如下:
<!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" --> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置逻辑视图的前缀 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 配置逻辑视图的后缀 --> <property name="suffix" value=".jsp" /> </bean>
- 逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为ItemList,则最终返回的jsp视图地址:
- “WEB-INF/jsp/itemList.jsp”
- 最终jsp物理地址:前缀+逻辑视图名+后缀
-
3.6.1 action示例
/** * springmvc - handler处理器 * * 定义class - XxxxAction * 定义具体操作控制方法 * */ @Controller //@RequestMapping("/customer") //url访问时,父结构 public class CustomerActionTest { /** * 注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射。* * 根据@ResquestMapping定义的url匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。 * HandlerMethod对象中封装url对应的方法Method * * @RequestMapping:定义请求url到处理器功能方法的映射 * */ @RequestMapping("/queryCustomers") public ModelAndView queryCustomers(){ System.out.println("----------queryCustomers----------"); // 使用ModelAndView传递数据及视图view -- 了解 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("data","Test"); //request.setAttribute() modelAndView.setViewName("mav"); return modelAndView; } /** 视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,这个视图解析器支持JSP视图解析 逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为ItemList,则最终返回的jsp视图地址: "WEB-INF/view/itemList.jsp" 最终jsp物理地址:前缀 + 逻辑视图名 + 后缀 */ @RequestMapping("/addCustomer") public String addCustomer(HttpServletRequest request) { request.setAttribute("info","request 233"); System.out.println("--------addCustomer----------"); return "customer/add"; } }
4.参数绑定
-
4.1 默认支持的参数类型
-
4.1.1 处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值。
- HttpServletRequest
- HttpServletResponse
- HttpSession
-
4.1.2 Model/ModelMap
-
Model
- 除了ModelAndView以外,还可以使用Model来向页面传递数据,Model是一个接口,在参数里直接声明model即可。
- 如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值替代。
- 不管是Model还是ModelAndView,其本质都是使用Request对象向jsp传递数据。
-
ModelMap
- ModelMap是Model接口的实现类,也可以通过ModelMap向页面传递数据
- 使用Model和ModelMap的效果一样,如果直接使用Model,springmvc会实例化ModelMap。
-
-
-
4.2 绑定简单类型
- 当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。
- 这样,从Request取参数的方法就可以进一步简化。
- 即,action方法接收参数的形参命名与请求参数的命名一致时,会自行进行参数绑定。省去了 Object obj = (Object)request.getParameter(“xx”);的过程
-
4.2.1 支持的数据类型
- 参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
- 整形:Integer、int
- 字符串:String
- 单精度:Float、float
- 双精度:Double、double
- 布尔型:Boolean、boolean
- 说明:对于布尔类型的参数,请求的参数值为true或false。或者1或0
- 请求url:
- 处理器方法:
- public String editItem(Model model,Integer id,Boolean status)
@Controller public class AdminAction { @Autowired private AdminService adminService; /** * 参数绑定 * 1:接收url中参数数据 * url?参数=value * 表单 * a) servlet方式 HttpServletRequest request * request.getParameter(name) * * b) 绑定简单参数类型 * 请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定 * springmvc - 类型转换 * * 2:传递数据到下一个url(view) * a) 默认支持的web参数类型--与servlet中的一样 * HttpServletRequest * HttpServletResponse * HttpSession * * b) request域数据 -- springMVC中 * Model * ModelMap --> Map * * c) 以pojo(实体对象)来进行接收,属性名与参数名要保持一致 * pojo对象中属性名和表单中input的name属性一致 * * springmvc - 默认类型转换 * 基本类型 - 若数据填写为空,因为基本类型不可为null - 400错误 * - 包装类即可 * * java.util.Date * 由于日期数据有很多种格式,springmvc无法自动转换字符串为日期,所以需要自己定义转换方法。 * 自定义DateConverter utils下 * * */ @RequestMapping("/login") /* 即,这里的userCode,password与页面上传递的请求参数一致 */ public String login(String userCode, String password, HttpSession session, HttpServletRequest request, Model model, ModelMap modelMap){ System.out.println(userCode + "\t" + password); Admin admin = adminService.login(userCode,password); if (admin == null){ request.setAttribute("info","用户名或密码错误"); model.addAttribute("info1","用户名或密码错误1"); // model用的比较多 modelMap.addAttribute("info2","用户名或密码错误2"); // 知道就行 /* * 跳转至url, String - 默认对应的为 视图解析器 + String + 后缀 * 由于login不在view配置的视图解析器下,所以不能这么写 * forward:url -- 请求转发,可以保留参数 * redirect:url -- 重定向 * */ return "forward:login.jsp"; } else{ session.setAttribute("admin",admin); return "index"; } } }
-
4.2.2 @RequestParam
- 使用@RequestParam常用于处理简单类型的绑定。
- value:参数名字,即入参的请求参数名字,如value=“itemId”表示请求的参数 区中的名字为itemId的参数的值将传入
- required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错
- TTP Status 400 - Required Integer parameter ‘XXXX’ is not present
- defaultValue:默认值,表示如果请求中没有同名参数时的默认值
@RequestMapping("/itemEdit") public String queryItemById(@RequestParam(value = "itemId", required = true, defaultValue = "1") Integer id, ModelMap modelMap) { // 根据id查询商品数据 Item item = this.itemService.queryItemById(id); // 把商品数据放在模型中 modelMap.addAttribute("item", item); return "itemEdit"; }
-
4.3 绑定pojo类型
- 要求:pojo对象中的属性名和表单中input的name属性一致。
- 请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
- 注意:
- 提交的表单中不要有日期类型的数据,否则会报400错误。如果想提交日期类型的数据需要用到后面的自定义参数绑定的内容。
- pojo类举例
public class Customer { private String custName; private String custLevel; private String custSource; // 由于日期数据有很多格式,所以没办法自动转换,要自己定义,否则400报错 private Date custDate; private String custPhone; // 如果是 int 填写时输入为空时,则会报错400,基本类型不能为null.换成Integer可以为null private Integer custYear; private String custAddress; private String custZip; private String custFax; private String custWebsite; ...
- 接收方法
@Controller public class CustomerAction { /** * c) 以pojo(实体对象)来进行接收,属性名与参数名要保持一致 * pojo对象中属性名和表单中input的name属性一致 * * springmvc - 默认类型转换 * 基本类型 - 若数据填写为空,因为基本类型不可为null - 400错误 * - 包装类即可 * * java.util.Date * 由于日期数据有很多种格式,springmvc无法自动转换字符串为日期,所以需要自己定义转换方法。 * 自定义DateConverter utils下 * */ @RequestMapping("/customer/add") public String addCustomerAction(Customer customer){ System.out.println(customer); return ""; } }
-
4.4 解决编码乱码问题
-
在web.xml中加入
<!-- spring提供的编码过滤器 -->
<filter>
<filter-name>springUtf8Encoding</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springUtf8Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-
对于get请求中文参数出现乱码解决方法有两个:
- 修改tomcat配置文件
- 另外一种方法对参数进行重新编码:
String userName new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
- ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
-
4.5 自定义参数绑定
-
在商品修改页面可以修改商品的生产日期,并且根据业务需求自定义日期格式。
-
由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。
-
前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。
-
一般使用mvc:annotation-driven/注解驱动加载处理器适配器,可以在此标签上进行配置。
-
自定义Converter
/** * springmvc - java.util.Date -- 自定义日期类型转换器 * * Converter<S, T> * S:source 需要转换的源的类型 * T:target,需要转换的目标类型 * */ public class DateConverter implements Converter<String,Date>{ @Override public Date convert(String source) { try { // 把字符串转换为日期类型 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = simpleDateFormat.parse(source); return date; } catch (ParseException e) { // e.printStackTrace(); } // 如果转换异常则返回空 return null; } }
- 配置Converter
- 方法1
<!-- 这里是对注解驱动进行了修改 --> <mvc:annotation-driven conversion-service="conversionService"/> <!-- 转换器配置 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.yiran.mvc.utils.DateConverter" /> </set> </property> </bean>
- 方法2
<!--注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="customBinder"></property> </bean> <!-- 自定义webBinder --> <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="conversionService" ref="conversionService" /> </bean> <!-- 转换器配置 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.igeek.springmvc.convert.DateConverter" /> </set> </property> </bean>
- 注意:此方法需要独立配置处理器映射器、适配器,不再使用mvc:annotation-driven/
-
5.HrefAction
- 在开发中往往我们会将页面放入WEB-INF目录下,因为该目录下的页面无法被直接访问,保证了安全性。
- 那么在超链接中我们就无法直接链接页面地址,而是通过一个HrefAction的请求映射类来帮助我们进行页面跳转
- 在页面上我们会以 /href?name=xxxx 来请求该处理器,然后通过该处理器进行页面跳转。
@Controller
public class HrefAction {
/** 用于实现页面超链接的跳转,因为页面放在WEB-INF 下,必须通过forward才可以访问,即这里的return */
@RequestMapping("/href")
public String href(String name){
return name; // == request.forward 请求转发
}
}
6.Vo
- 有时候,我们提交的数据,不仅是实体类中包含的属性,例如手机价格的范围,并不在bean类的属性中。这时候我们需要Vo来包含这些属性,以便简化编程。
- 例如,需要查询客户年限范围。
- 创建CustomerVo来包含客户年限范围
public class CustomerVo {
/* 表单参数 对象名.属性 */
private Customer customer;
private Integer minYear;
private Integer maxYear;
- 如何在action中接收
@RequestMapping("/customer/list")
// 这是以前使用的方法,使用Vo更加简单
// public String queryCustomer(Model model,Customer cust,Integer minYear,Integer maxYear){
public String queryCustomer(Model model, CustomerVo customerVo){
/* Vo中的关联对象,在表单验证中提交时,不能直接写其关联对象的属性名,而要写对象名.属性名 */
System.out.println(customerVo);
List<Customer> list = new ArrayList<>();
model.addAttribute("list",list);
return "";
}
-
如何在表单中定义name属性,我们会发现,如果按往常一样直接使用属性名,那么无法接收到。
- 我们可以看到 Customer 类是Vo类的时候,命名为customer ,所以我们在表单中的name,应该为 customer.属性名 这样就可以接收到了。
- 因为customer相当于Vo的一个属性,这个属性为一个类,这样理解比较容易。
-
服务器启动时加载servlet
- 而不是访问时才加载
- 在web.xml中配置
- <load-on-startup>
- load-on-startup 元素标记容器是否应该在web应用程序启动的时候就加载这个servlet,(实例化并调用其init()方法)。在springmvc中是spring初始服务,也就是前端控制器
- 它的值必须是一个整数,表示服务被加载的先后顺序。
- 如果该元素的值为负数或者没有设置,则容器会当服务被请求时再加载。
- 如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,服务的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
-
如果配置url-pattern 为 / 而不是 *.action
- 需要在spring-web.xml中配置排除静态文件的访问,不以.action这样的方式来访问,不走requestMapping,屏蔽静态资源