springmvc 从入门到总结
来源:互联网 发布:靠谱代购淘宝店 知乎 编辑:程序博客网 时间:2024/05/19 21:17
springMvc的总结:(推荐,总共有十五章)
http://www.cnblogs.com/liukemng/p/3751338.html
框架
拦截器不拦截静态资源
http://www.cnblogs.com/banning/p/6195072.html
Spring
学习版本: 4.3.0
框架认识
框架学起来比较简单
但也有难的地方,难是难在底层原理
用了框架之后,写代码就非常简单,因为框架会完成一部分代码,
我们只要按框架的规则去使用就可以了
学习框架的方法:
与学习初级基础有所不同,
基础学习都是学习基本语法,完成简单的案例,逐步理解面向对象的编程思想.
框架属于中高级的学习,要运用面向对象的进行编程,接口编程
能够自已完成业务.熟悉业务.能够架构一个项目,属性框架的原理
框架学习程度:
相用框架
理解框架原理、走源码
自己编写框架部分
框架的由来
Md1
Md2
Jsp/servlet 的 mvc回顾
当一个方法中有部分代码在不断重复时,抽取出来做一个方法
当很多类在操作同一段代码时,抽出来做一个类
当很多类在做同一类事情的时候,抽出来做一个jar包或做成框架
这就是框架
框架,替程序员完成一部分代码,从而提高开发效率
框架就是一个模板,
Web应用的框架:webwork,jsf, struts1, struts2,springmvc
Mvc框架的工作
Servlet:
将页面请求映射到java类,也就是后台
接收并处理页面提交的数据
调用业务逻辑方法处理业务结果,将数据封装准备渲染到页面
控制页面跳转
Mvc的V层:
将页面请求映射到java类,也就是后台
获取并封装好页面提交的数据
渲染数据到页面
控制页面跳转
Spring下载
http://repo.springsource.org/libs-release-local/org/springframework/spring
向下拉选中需要下载的版本。
点击相应需要下载的zip,window版本直接下zip即可
Spring mvc
Spring mvc是一个轻量级的基于请求响应的mvc框架。Mvc框架一般都是基于请求响应的(JSF是基于事件驱动的框架)。
Spring mvc的优势:
1. 性能较struts2好(struts2是快速开发)
2. Spring mvc使用简单,配置便捷,易上手
3. 天生与spring无缝集成(使用spring的IOC和AOP)(struts2也有可以与spring集成,但是需要插件需要配置)
4. 使用约定大于配置(只要遵守spring mvc的配置约定,那么编码非常简结)
5. 能进行简单的junit测试
6. 支持restful风格
7. 异常处理
8. 本地化、国际化、数据验证、类型转换等等
9. 拦截器
使用的人多,使用的公司多
Spring mvc 简单的结构流程图
Springmvc工作流程描述
1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象
(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)
4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等
数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
7. ViewResolver 结合Model和View,来渲染视图
8. 将渲染结果返回给客户端。
Hello spring mvc配置开发
1. 导入jar
commons-logging-1.1.3.jar
jstl-2.4.jar
servlet-api.jar
spring-beans-4.3.0.RELEASE.jar
spring-context-4.3.0.RELEASE.jar
spring-context-support-4.3.0.RELEASE.jar
spring-core-4.3.0.RELEASE.jar
spring-expression-4.3.0.RELEASE.jar
spring-web-4.3.0.RELEASE.jar
spring-webmvc-4.3.0.RELEASE.jar
2. 配置web.xml,配置spring mvc的分发器(和servlet配置一样)DispatcherServlet,需要在tomcat启动的时候就加载
<load-on-startup>1</load-on-startup>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3. 添加springmvc的配置文件,默认在src下添加dispatcherServletName-servlet.xml,
注意:dispatcherServletName是web.xml中servlet-name的值,根据这里的配置,应该叫:springmvc-servlet.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
</beans>
注:这个配置文件中的内容如何不会写,那么可以到spring的zip中找到dosc/spring-frameworkreference/html
找到The Web模块下的The DispatcherServlet 下的Default DispatcherServlet Configuration配置
4. 编写Controller
public class HelloControllerimplements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequestarg0, HttpServletResponsearg1)throws Exception {
//ModelAndView是封装要显示到页面的数据
ModelAndView mv =new ModelAndView();
//页面的数据
mv.addObject("msg","你好 spring mvc");
//配置视图的名称
mv.setViewName("hello");
return mv;
}
}
5. 配置springmvc配置文件(给第3步的配置文件添加内容)
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置页面渲染器,到dosc/html/index.html中搜索Reslover可以找到 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置请求的处理类 -->
<bean name="/hello.do" class="com.yirong.controller.HelloController"></bean>
</beans>
6. 请求结果
Spring mvc注解开发
1. 倒入jar
commons-logging-1.1.3.jar
jstl-2.4.jar
servlet-api.jar
spring-aop-4.3.0.RELEASE.jar
spring-beans-4.3.0.RELEASE.jar
spring-context-4.3.0.RELEASE.jar
spring-context-support-4.3.0.RELEASE.jar
spring-core-4.3.0.RELEASE.jar
spring-expression-4.3.0.RELEASE.jar
spring-web-4.3.0.RELEASE.jar
spring-webmvc-4.3.0.RELEASE.jar
2. 配置web.xml
<!-- 注解的方式 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param> <!-- 到the web文档中可以查找获得-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value> <!--此配置文件在源码下-->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3. 编写controller
package com.yirong.controller.annotation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller //表示这个是一个Controller
public class HelloWorldController {
@RequestMapping("/helloWorld") //请求此方法
public String helloWorld(Modelmodel) {
model.addAttribute("msg","Hello World! 你好springmvc注解 ");
return "hello";//视图的名称
}
@RequestMapping("/helloWorld1")//请求此方法
public ModelAndView helloWorldreq(HttpServletRequestarg0, HttpServletResponsearg1)throws Exception {
//ModelAndView是封装要显示到页面的数据
ModelAndView mv =new ModelAndView();
//页面的数据
mv.addObject("msg","你好 spring mvc");
//配置视图的名称
mv.setViewName("hello");
return mv;
}
}
4. 配置springmvc.xml,这个文件需要和源码放在一起src/*.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置页面渲染器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀,页面路径默认在webContent下-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--扫描这个文件夹下的类表示是注解的controller。 到the web文档中可以查找获得-->
<context:component-scan base-package="com.yirong.controller.annotation" />
</beans>
5. 效果:
Controller配置方式
1. 配置开发
2. 注解开发
3. Key对应url请求名的方式
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置HandlerAdapter 如果这里不配置,那么请求一定要带上web中配置的结尾,比如.do-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置页面渲染器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀,页面路径默认在webContent下-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.do">helloController</prop>
</props>
</property>
</bean>
<bean name="helloController" class="com.yirong.controller.HelloController"></bean>
</beans>
4. 控制器类名的方式配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 配置HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置HandlerAdapter 如果这里不配置,那么请求一定要带上web中配置的结尾,比如.do-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置页面渲染器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀页面默认在webContent下-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 控制器类名的方式配置 hello*.do的请求将被匹配-->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean name="helloController" class="com.yirong.controller.HelloController"></bean>
</beans>
Spring mvc结果跳转
1. 设置 ModelAndView对象,视图解释器根据设置的view的名称进行跳转
视图解释器根据springmvc配置文件中的页面的前缀路径+视图名称+springmvc配置文件中的页面的后缀,找到指定页面。
@Override
public ModelAndView handleRequest(HttpServletRequestarg0, HttpServletResponsearg1)throws Exception {
//ModelAndView是封装要显示到页面的数据
ModelAndView mv =new ModelAndView();
//页面的数据
mv.addObject("msg","你好 spring mvc");
//配置视图的名称
mv.setViewName("hello");
return mv;
}
@RequestMapping("/helloWorld")//请求此方法
public String helloWorld(Modelmodel) {
model.addAttribute("msg","Hello World! 你好springmvc注解 ");
return "hello";//视图的名称
}
2. 通过servletApi跳转,不使用springmvc的视图解释器
@RequestMapping("/helloWorld1")//请求此方法
public voidhelloWorldreq(HttpServletRequestarg0, HttpServletResponsearg1)throws Exception {
arg1.getWriter().println("你好,springmvc servlet");
//servlet的重定向和转向设置值等在这里都可以使用
}
3. Springmvc实现重定向和转发,没有视图渲染器,页面在webcontent下,转发,需要带上.jsp没有用到视图渲染器
@RequestMapping("/zhuanfa")
public String zhuanfa(){
return "forward:zhuanfa.jsp"; //转发 地址栏不变
//return "redirect:zhuangxiang.jsp"; //转向 地址栏变
}
4. Springmvc实现重定向和转发,有视图渲染器,转向不需要视图渲染器
@RequestMapping("/zhuanfa")
public String zhuanfa(){
return "zhuanfa"; //默认转发
}
Spring mvc 是单例的
1. 给controller添加一个构造方法,在启动时执行一次,而后访问时不会再执行
public HelloWorldController(){
System.out.println("spring mvc 构造方式");
}
Spring mvc接收页面简单数据
1. 创建一个注解方式的spring mvc项目环境,在controller中添加以下方法
/**
* url参数数据提交,在这里获取数据
* @param name
* @return
*/
@RequestMapping("/datas")
public String getData(Stringname){
System.out.println(name);
return "wel";
}
2. 访问,注意参数名与上面方法名的形参名相同
http://localhost:8080/springMvcTest/datas.do?name=aacc
3. 如果url上的参数名与方法是的形参名不同也可以传递参数,改造方法:
/**
* url参数数据提交,在这里获取数据
* @param name
* @return
*/
@RequestMapping("/datas")
public String getData(@RequestParam("un")Stringname){
System.out.println(name);
return "wel";
}
4. 访问
http://localhost:8080/springMvcTest/datas.do?un=aaccsdf
Spring mvc接收对象数据
要求表单中的name的名称与实体的属性名相同,controller中的方法的形参是实体的对象即可。
spring mvc对基本数据类型会自动转换。
Spring mvc会将传递的值封装到对象中去,并且与形参的名称没有关系。
1. 在controller中添加一个方法
/**
* url参数数据提交,在这里获取对象数据
* @param name
* @return
*/
@RequestMapping("/dataObj")
public String getDataObj(User user){
System.out.println(user.toString());
return "wel";
}
2. 添加User对象,属性需要有get set方法
package com.yirong.controller.annotation;
public class User {
private Stringname;
private Integerage;
private Stringtel;
public String getName() {
return name;
}
public void setName(Stringname) {
this.name =name;
}
public Integer getAge() {
return age;
}
public void setAge(Integerage) {
this.age =age;
}
public String getTel() {
return tel;
}
public void setTel(Stringtel) {
this.tel =tel;
}
@Override
public String toString() {
return "User [name=" +name +", age=" + age +", tel=" +tel + "]";
}
}
3. 效果
http://localhost:8080/springMvcTest/dataObj.do?name=myname&age=1
Spring mvc将数据显示到UI
ModelAndView的方式
public class HelloControllerimplements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequestarg0, HttpServletResponsearg1)throws Exception {
//ModelAndView是封装要显示到页面的数据
//这相当于是request.setAttribute的方式
ModelAndView mv =new ModelAndView();
//页面的数据
mv.addObject("msg","你好 spring mvc");
//配置视图的名称
mv.setViewName("hello");
return mv;
}
}
1. 页面用el表达式即可
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>springmvc转发</title>
</head>
<body>
springmvc转发sdf
<br>
${msg}
</body>
</html
ModelMap的方式
1. 注:modelmap一定要放在controller的方法中做为形参
/**
* url参数数据提交,在这里获取对象数据
* @param name
* @return
*/
@RequestMapping("/dataObj")
public String getDataObj(Useruser,ModelMap modelMap){
System.out.println(user.toString());
//将数据显示到页面
modelMap.addAttribute("myvalue","值,va");
return "wel";
}
2. 页面
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>springmvc转发</title>
</head>
<body>
springmvc转发sdf
<br>
${myvalue }
</body>
</html>
3. 效果
ModelAndView与ModelMap方式比较
相同点:都可以将数据封装显示到视图
不同点:ModelAndView可以指定跳转的视图,而ModelMap不能
ModelAndView需要视图解析器,ModelMap可以不需要
Spring mvc解决乱码
Get方式乱码
配置tomcat即可
找到conf/server.xml中端口设置的地方,添加 URIEncoding="UTF-8"
添加完成之后:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8" />
1. 传递中文到controller
/**
* url参数数据提交,在这里获取数据
* @param name
* @return
*/
@RequestMapping("/datas")
public String getData(@RequestParam("un")Stringname,ModelMap map){
System.out.println(name);
map.addAttribute(“myvalue”,name);
return "wel";
}
http://localhost:8080/springMvcTest/datas.do?un=你好springmvc
2. 效果,中文在controller中拿到是乱码
解决之前:乱码
解决之后:
再传递到页面(注:页面的编码要是utf-8,浏览器的编码也需要是utf-8):
Post方式乱码
Spring mvc 中解决乱码是通过CharacterEncodingFilter过滤器来解决的,因此需要在web.xml中配置。并且CharacterEncodingFilter主要是用于解决post请求的乱码,
get请求方式的乱码需要用到tomcat或jsp页面设置的方式进行解决
注:此配置需要配置在DispatcherServlet之前
<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. 页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>乱码解决</title>
</head>
<body>
<form action="/springMvcTest/datas.do" method="post">
<input type="text" name="un" />
<input type="submit" value="提交" />
</form>
</body>
</html>
2. 效果:
Spring mvc url请求风格1
package com.yirong.controller.annotation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller //表示这个是一个Controller
@RequestMapping("/hello2")
public class Hello2Controller {
@RequestMapping(params="method=add",method=RequestMethod.POST) //请求此方法一定要是post方式
public String helloWorld(Model model) {
model.addAttribute("msg", "Hello World! 你好springmvc注解 params");
return "WEB-INF/jsp/hello"; //视图的名称
}
}
package com.yirong.controller.annotation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller //表示这个是一个Controller
@RequestMapping("/hello2")
public class Hello2Controller {
@RequestMapping(params="method=add",method=RequestMethod.GET) //请求此方法一定要是GET方式
public String helloWorld(Model model) {
model.addAttribute("msg", "Hello World! 你好springmvc注解 params");
return "WEB-INF/jsp/hello"; //视图的名称
}
}
Restful风格和@PathVariable
Restful风格:轻量级,安全,效率高
Controller中的方法:
@RequestMapping("/{uid}/del/{id}")
public String del(@PathVariable Integerid,@PathVariable("uid") Integer uid,ModelMapmodelMap){
System.out.println(id);
System.out.println(uid);
//将数据显示到页面
modelMap.addAttribute("myvalue",id);
return "wel";
}
@PathVariable表示这个参数是路径带过来的参数
Restful风格的写法还可以这样:
@RequestMapping("/del/{id}/{uid}")
@RequestMapping("/{id}/del//{uid}")
效果:
http://localhost:8080/springMvcTest/111/del/222.do
详解@RequestMapping
@RequestMapping可以修饰在类上面,表示指定的目录为这个类请求的url,也可以修饰在方法上面表示请求的是某个方法
标识url的方式:@RequestMapping(“url”)
表识参数和方法还有头的请求方式:
@RequestMapping(value="/rmtest",params={"name","age!=10"},method=RequestMethod.GET,headers={"Accept-Language=zh-CN,zh;q=0.8"})
Value表示:url
Params表示:请求的url必须带上指定参数,而且age的值!=10,否则404
Method表示:请求的方式一定指定方式,这里是GET,否则404
Headers表示:http请求的头的内容,其中这里指定Accept-Language的值一定要是zh-CN,zh;q=0.8,否则404
例:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller //表示这个是一个Controller
public class RmTest {
@RequestMapping(value="/rmtest",params={"name","age!=10"},method=RequestMethod.GET,headers={"Accept-Language=zh-CN,zh;q=0.8"})//请求此方法
public String helloWorld(Modelmodel) {
model.addAttribute("msg","Hello World! 你好springmvc注解 rmtest");
return "WEB-INF/jsp/hello";//视图的名称
}
}
效果:
详解@RequestMapping ant风格url
此方式了解即可
Ant风格资源地址支持3种匹配符:
? : 匹配文件名中的一个字符
* : 匹配文件名中的任意字符
** : 匹配多层路径
@RequestMapping对ant风格url的支持,例:
例:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller //表示这个是一个Controller
public class RmTest {
@RequestMapping("/antUrl/*/t")//请求此方法
public String testAntUrl(Modelmodel) {
model.addAttribute("msg","Hello World! 你好springmvc注解 anturl");
return "WEB-INF/jsp/hello";//视图的名称
}
}
详解@PathVariable
详解Restful
http://kb.cnblogs.com/page/186516/
http://www.infoq.com/cn/articles/rest-introduction
比如:
案例
package com.yirong.controller.annotation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller // 表示这个是一个Controller
public class RestfulTest {
@RequestMapping(value="/testRestfulUrl",method=RequestMethod.POST)
public String add(Ordero, Modelmodel) {
System.out.println(o.toString());
model.addAttribute("msg","Hello World! 你好springmvc注解 restful 添加 post 请求");
return "order/add";
}
@RequestMapping(value="/testRestfulUrl/{id}",method=RequestMethod.GET)
public String get(@PathVariable("id") Integer id, Modelmodel) {
System.out.println(id);
model.addAttribute("msg","Hello World! 你好springmvc注解 restful 通过id查一个对象的信息 get请求");
return "order/add";
}
@RequestMapping(value="/testRestfulUrl/{id}",method=RequestMethod.DELETE)
public String delete(@PathVariable("id") Integer id, Modelmodel) {
System.out.println(id);
model.addAttribute("msg","Hello World! 你好springmvc注解 restful 删除 delete请求");
return "order/add";
}
@RequestMapping(value="/testRestfulUrl/{id}",method=RequestMethod.PUT)
public String put(@PathVariable("id") Integer id, Modelmodel) {
System.out.println(id);
model.addAttribute("msg","Hello World! 你好springmvc注解 restful 修改 put请求");
return "order/add";
}
}
页面:在webContent/order/下
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
添加:<br />
<form action="/springMvcTest/testRestfulUrl.do" method="post">
<input type="text" name="orderName" />
<input type="text" name="number" />
<input type="submit" value="提交" />
</form>
获得:<br />
<a href="/springMvcTest/testRestfulUrl.do/1">获取id=1的数据</a>
删除:<br />
<form action="/springMvcTest/testRestfulUrl.do/1" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="提交" />
</form>
修改<br />
<form action="/springMvcTest/testRestfulUrl.do/1" method="post">
<input type="hidden" name="_method" value="PUT"/>
<input type="submit" value="提交" />
</form>
<br />
<br />
<br />
${msg}
</body>
</html>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<!-- HiddenHttpMethodFilter是spring3.0之后新增的一个过滤器,可以将post请求转为put和delete请求,
对实现rest风格有了更好的支持 -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<!-- 配置的方式
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping> -->
<!-- 注解的方式-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Springmvc.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-lazy-init="true">
<!-- 配置页面渲染器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀 -->
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:annotation-driven /> <!-- 基于Schema-based XML的配置定义模式 -->
<context:component-scan base-package="com.yirong.controller.annotation" />
</beans>
详解@RequestParam
在上面例子的类中添加以下方法:
@RequestMapping(value="/testRequestParam")
public String testRequestParam(@RequestParam(value="userName") String userName,
@RequestParam(value="age",required=true,)Integer age
//@RequestParam(value="age",required=false,defaultValue="0")int age, Modelmodel) {
model.addAttribute("msg","Hello World! 你好springmvc注解 requestParam "+userName+" age="+age);
return "order/list";
}
List.jsp:在webContent/order/下
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>requestParam</title>
</head>
<body>
<form action="/springMvcTest/testRequestParam" method="post">
<input type="text" name="userName" />
<input type="text" name="age" />
<input type="submit" value="提交" />
</form>
${msg }
</body>
</html>
注:@RequestParam(value="age",required=true)的value表示为参数名称,在form表单中需要一一对应.
Required=true表示此参数是必须的,如果不写或把值改为false表示该参数不是必须的,但是要注意:如果是一个Integer类型的值,也就是数字,那么在这里接收参数的类型一定要是Integer对象,不能是int类型,否则当此参数被用到时而又并未给相应的值(当此参数不是必须时),那么就会出现异常
如果一定需要传递int类型,那么需要添加一个配置:@RequestParam(value="age",required=false,defaultValue="0")int age
表示默认值为0,如果没有传递age,那么默认为0.
了解@RequestHeader
此注解与详解@RequestMapping的headers参数是一个意思,用法与@RequestMapping相同,表示指定请求头包含指定参数名.了解即可.
详解@CookieValue
此注解可以让处理方法的入参绑定某个Cookies的值,表示是从cookies中取指定参数名称的值.
每一次请求都有一个JSESSIONID,那么我们可以通过@CookiesValue这个注解将JSESSIONID通过处理方法入参的方式获得
@RequestMapping(value="/testCookiesValue")
public String testCookiesValue(@CookieValue(value="JSESSIONID") String sessionId,
@RequestParam(value="age") Integerage, Modelmodel) {
model.addAttribute("msg","Hello World! 你好springmvc注解 @CookieValue "+sessionId+" age="+age);
return "order/list";
}
Cookies.jsp:在webcontent/order/下
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>requestParam</title>
</head>
<body>
<form action="/springMvcTest/testCookiesValue" method="post">
<input type="text" name="age" />
<input type="submit" value="提交" />
</form>
${msg }
</body>
</html>
效果:正常的取到cookies中的值
详解将Pojo做为参数传递
在前面已实现将对象做为参数传递到spring mvc的controller中,在传递的过程中,spring mvc
会将指定的参数名自匹配到pojo的属性名中,并且还会填充值到pojo的属性中.且支持级联属性.
案例1:
注:controller中@RequestMapping的写法,在类上有注解,在方法上也有注解,并且处理的方法中的参数为Model model 这是对应的,不能错写.
另:Model model可以去掉不要,即类和方法同时有@RequestMapping注解那么处理方法可添加Model model可不添加,但不能添加ModelMap做为视图数据封装类
OrderController:
package com.yirong.controller.annotation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("order")
@Controller //表示这个是一个Controller
public class OrderController {
@RequestMapping("/add")//请求此方法
public String add(Orderorder,Model model) {
System.out.println(order.toString());
model.addAttribute("msg","添加订单成功 "+order.toString());
return "wel";//视图的名称wel.jsp页面只是一个成功页面,内容为”成功页面”
}
}
Order.java
package com.yirong.controller.annotation;
public class Order {
private StringorderName;
private Integernumber;
private Useruser;
public String getOrderName() {
return orderName;
}
public void setOrderName(StringorderName) {
this.orderName =orderName;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integernumber) {
this.number =number;
}
public User getUser() {
return user;
}
public void setUser(Useruser) {
this.user =user;
}
@Override
public String toString() {
return "Order [orderName=" +orderName +", number=" +number + ", user=" +user +"]";
}
}
User.java
package com.yirong.controller.annotation;
public class User {
private Stringname;
private Integerage;
private Stringtel;
public String getName() {
return name;
}
public void setName(Stringname) {
this.name =name;
}
public Integer getAge() {
return age;
}
public void setAge(Integerage) {
this.age =age;
}
public String getTel() {
return tel;
}
public void setTel(Stringtel) {
this.tel =tel;
}
@Override
public String toString() {
return "User [name=" +name +", age=" + age +", tel=" +tel + "]";
}
}
addOrder.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
添加订单:<br />
<form action="/springMvcTest/order/add" method="post">
订单名称:<input type="text" name="orderName" /><br />
数量:<input type="text" name="number" /><br />
用户名:<input type="text" name="user.name" /><br />
年龄:<input type="text" name="user.age" /><br />
电话:<input type="text" name="user.tel" /><br />
<input type="submit" value="提交" /><br />
</form>
<br />
</body>
</html>
案例2:
注:controller中@RequestMapping的写法,只在方法上也有注解,并且处理的方法中的参数为ModelMap modelMap这是对应的,不能错写.
另:ModelMap modelMap可以去掉不要,即只方法有@RequestMapping注解那么处理方法可添加ModelMap modelMap可不添加,但不能添加Model做为视图数据封装类
Order2Controller:
package com.yirong.controller.annotation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller //表示这个是一个Controller
public class Order2Controller {
@RequestMapping("/order2")//请求此方法
public String order2(Orderorder,ModelMap modelMap) {
System.out.println(order.toString());
modelMap.addAttribute("msg","添加订单成功 "+order.toString());
return "wel";//视图的名称wel.jsp页面只是一个成功页面,内容为”成功页面”
}
}
Order.java和User.java参考案例1
addOrder.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
添加订单2:<br />
<form action="/springMvcTest/order2" method="post">
订单名称:<input type="text" name="orderName" /><br />
数量:<input type="text" name="number" /><br />
用户名:<input type="text" name="user.name" /><br />
年龄:<input type="text" name="user.age" /><br />
电话:<input type="text" name="user.tel" /><br />
<input type="submit" value="提交" /><br />
</form>
</body>
</html>
详解spring mvc接收servlet原生api参数
Spring mvc的Handler方法可以接受Servlet api的以下类型做为参数:
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
例:
添加一个方法到controller中
@RequestMapping("/servApi")
public void servApi(HttpServletRequestrequest,HttpServletResponseresponse,Writerout)throws IOException {
request.setCharacterEncoding("UTF-8");
System.out.println(request+" , "+response);
out.write("spring mvc servlet api");
//return "wel"; //视图的名称
}
页面请求:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>servlet </title>
</head>
<body>
<a href="/springMvcTest/servApi">servlet 原生api</a>
</body>
</html>
效果:
详解spring mvc 处理模型数据
Spring mvc 会将模型数据对象中的数据添加到request对象中
原码:InternalResourceView.renderMergedOutputModel() -> AbstractView.exposeModelAsRequestAttributes()
ModelAndView
ModelAndView是一个视图数据封装器,其包含了视图信息和模型数据信息,在controller处理类返回该对象时,直接new操作即可
例:
/**
* ModelAndView 的使用
* 可以通过new ModelAndView时将视图名称添加到ModelAndView中
* 也可以通过modelAndView.setViewName("wel");设置
* @return
*/
@RequestMapping("testModAndView")
public ModelAndView testModelAndView(){
ModelAndView modelAndView =new ModelAndView("wel");
modelAndView.addObject("time",new Date());
return modelAndView;
}
Map和Model
Map and Model 需要写在controller类的处理类的形参中,以参数的方式处理模型数据,其类型为org.springframework.ui.Model和
org.springframework.ui.ModelMap或java.util.Map,spring mvc框架在渲染视图时会自动将需要渲染的数据添加到模型中.
Spring mvc 在调用方法前会创建一个隐含的模型对像作为模型数据的存储容器.如果方法的入参为Map或Model类型时,spring mvc会将隐含模型的引用传递给入参.开发者可以通过入参对象访问到模型中所有的数据,也可以向模型中添加新的数据,以渲染到视图.
Spring mvc model类关系:
Controller类中的方法:
/**
* spring mvc 的controller类的处理方法的形参可以是一个map,而这个map其实是
* spring mvc提供的org.springframework.validation.support.BindingAwareModelMap的实例
* @return
*/
@RequestMapping("/testMap")
public String testMap(Map<String,Object>map){
map.put("msg",Arrays.asList("aa","bb","cc",map.getClass().getName()));
return "wel";
}
Wel.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>springmvc </title>
</head>
<body>
<br>
${msg }
</body>
</html>
Model 与 ModelMap入参的方式处理模型数据在前面章节中已有详细例子.
详解@SessionAttributes
如需在多个请求之间共享某个模型属性数据,则可以在controller类上添加此注解,@SessionAttribute注解只能添加在类上面
Spring mvc 会将在模型中对应的属性暂存到HttpSession中.
@SessionAttributes可以通过指定属性名将相应的值放入session以外,还可以通过模型属性中的对象类型将值放入到session中
例:
@SessionAttributes(types=User.class) 会将隐含模型中所有类型为User.class的属性和值添加到session中
@SessionAttributes(value={“username”,”age”}) 会将隐含模型中属性名为username和age的属性和值添加到session中
@SessionAttributes(types={User.class},value={“username”,”age”})同上意
1. @SessionAttributes 的Value属性表示是将指定的属性放进session
2. @SessionAttributes 的Type属性表示是将指定的类型的属性全放进session
3. @SessionAttributes注解只能添加在类上面
package com.yirong.controller.annotation;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
@SessionAttributes(value={"user"},types={String.class})
@Controller
public class ModelViewController {
@RequestMapping("/testSessionAttri")
public String testSessionAttri(Map<String,Object>map){
User user =new User();
user.setAge(10);
user.setName("张三");
user.setTel("13445678945");
map.put("user",user);
map.put("addr","shenzhen");
return "wel";
}
}
页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>springmvc </title>
</head>
<body>
<br >
request user: ${requestScope.user } <br >
session user: ${sessionScope.user } <br >
request addr: ${requestScope.addr }<br >
session addr: ${sessionScope.addr }<br >
</body>
</html>
详解@ModelAttribute
应用场景
通过一个修改操作来了解ModelAttribute使用场景
解决问题:
在更新之前应该从数据中根据ID拿出需要修改的数据对象A ,然后将要修改的数据填充到A对象中,那么不需要修改的数据在A对象中本身就存在而且是从数据库中填充的,这样更修后就不存在上所描述的问题.这就是ModelAttribute使用的场景(Struts2中有一个类似功能的拦截器)
代码:
package com.yirong.controller.annotation;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
//@SessionAttributes(value={"user"},types={String.class}) 注意这个要删除,否则有500 后面章节讲解
@Controller
public class ModelViewController {
@RequestMapping("/testModelAttribute")
//public String testModelAttribute(@ModelAttribute(“user”)Useruser) {
public String testModelAttribute(Useruser) {
System.out.println(user.toString());
return "wel";
}
/**
* 有@ModelAttribute标记的方法,会在每个目标方法执行之前被spring mvc框架调用
* @param id
* @param map
*/
@ModelAttribute
//不加此注解,在页面输入新数据点修改后,testModelAttribute方法打应的对象中tel的值为null
public void getUser(@RequestParam(value="id",required=false) Integer id
,Map<String,Object> map){
if (null != id) {
User user = new User();
user.setName("zhangsan");
user.setAge(12);
user.setTel("13400000000");
System.out.println("模拟从数据库中取数据完成 "+user.toString());
map.put("user", user);
}
}
}
test.jsp页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>springmvc </title>
</head>
<body>
<br />
模拟修改操作:<br />
原始数据:id : 1 name :zhangsan age: 12tel:13400000000<br />
修改后的值为: id : 1 name:lisi age:20 tel不修改<br />
<br />
<form action="/springMvcTest/testModelAttribute">
<input type="hidden" name="id" value="1" />
名称:<input type="text" name="name" value="zhangsan"/><br />
年龄<input type="text" name="age" value="12"/><br />
<input type="submit" value="修改" />
</form>
</body>
</html>
效果:
原理
根据上面例子,简单运行流程:
1. 并在执行testModelAttribute方法之前,执行@ModelAttribute注解的方法getUser,把获取的对象放进Map中,key为user
2. Spring mvcww map中取出user对象,并把表单中的数据封装到对象中的相应属性
3. 再执行testModelAttribute方法(也就是目标方法)
注:@ModelAttribute注解的方法中将对象放入到map时,key需要和目标方法的入参的类型首字母小写后的字符串相同
上例: testModelAttribute方法的入参类型是User,那么首字母小写后为user,则在@ModelAttribute注解的方法中的map设置值时的key也需要为user
走原码:在以下几个关键点打断点,然后观察map中对象的值的变化,可以看到封装流程
HandlerMethodInvoker
1. ->invokeHandlerMethod():
和:
ExtendedModelMap implicitModel) throws Exception {
2. ->resolveModelAttribute():
3. ->resolveHandlerArguments():
和:
再到:AbstractBindingResult->getModel()
原码原理:
1. 调用@ModelAttribute注解的方法后,把@ModelAttribute方法中的Map中的数据放在了implicitModel中.
2. 解析请求处理器的目标参数,数据来自WebDataBinder对象的target属性
a) 创建WebDataBinder对象,
b) 获得objectName属性:若attrName属性值为””,则objectName为类名第一个字母小写
i. 若目标方法的入参的Pojo使用了@ModelAttribute来修饰,那么attrName的值就为@ModelAttribute(value指定的值)
c) 获得target属性
i. 在implicitModel中查找attrName对应的属性值,若存在直接取
ii. 不存在,则验证当前Controller是否使用了@SessionAttributes注解,如用了则从session中取attrName所对应属性的值,如取不到则抛异常
iii. 如果没有用@SessionAttributes注解或@SessionAttributes中使用value的值指定的key和attrName不相匹配,那么通过反射创建pojo对象进行处理
3. Spring mvc 把表单的请求参数赋给了webDataBinder的target对应的属性,再将attrName和target赋给implicitModel,最后将对象(target)传给目标方法入参
Spring mvc 确定目标方法pojo类型入参的过程
1. Spring mvc框架在获取目标方法的参数时,首先判断入参的POJO是否有用@ModelAttribute注解,如果没有,则直接使用POJO的首字母小写后的字符串做为KEY
如果有使用则直接用@ModelAttribute注解的value的值做为KEY
2. 使用时在implicitModel中查找key对应的对象,存在就则为入参传入,如找不到key则则检查当前的Handler是否使用了@SessionAttributes注解,如果用了,且能在session中找到相应的key,则从session中取key,否则抛异常.如果没有用或用了但没有包含相应的KEY,则会通过反射POJO来处理
3. Spring mvc把key和pojo类型的对象保存到imlicitModel中,再保存到request中
最终得出@ModelAttribute注解的特点:
1. 有@ModelAttribute注解的方法会在每个目标方法执行之前被spring mvc调用
2. @ModelAttribute注解也可以用来修饰目标方法的POJO类型的入参,其value属性值有以下作用:
a) Spring mvc 会相济 value属性值在implicitModel中查找对应的对象,若存在则会直接传入到目标方法的入参中.
b) Spring mvc 会以 注解的value的值做为 key ,POJO做为value的方式存入到request中
@SessionAttributes与@ModelAttribute同用时的异常
根据以上原理分析,注解了@ModelAttribute时,当controller中没明确了标识了所需的key时,而又同时使用了@SessionAttributes注解,那么就会到session中去找@ModelAttribute所标识的key的值或因为默认的值与@SessionAttributes注解的key相同时,那么就可能会发生异常.
解决办法,@ModelAttribute注解value的值与@SessionAttributes注解的value的值不要相同,或如果没必要则不要随便注解@SessionAttributes
doDispatch
processDispatchResult
Render
注解详说:
http://www.cnblogs.com/xiepeixing/p/4243288.html
InternalResourceViewResolver
1. 若项目中使用了jstl,则spring mvc会自动把视图由InternalResourceView转为JstlView
2. 如果使用了jstl的fmt标签则需要在spring mvc的配置文件中配置国际化资源文件
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
3. 如果希望直接响应通过spring mvc渲染的页面,可以使用<mvc:view-controller>标签来实现
<mvc:view-controller
path="/springMvcTest/testJstlView" view-name="wel" />
<mvc:view-controller>
用于配置直接转发的页面,不需要经过controller,直接输入配置的/aa就会请求到wel视图
<mvc:view-controller
path="/aa"view-name="wel" />
这样的请求方式适用于,有些页面不需要任何controller处理逻辑就要响应的页面
注:如果需要用<mvc:view-controller>,那么一定要加上<mvc:annotation-driven />,否则除<mvc:view-controller>配置有效外,其他的url都为404
Spring mvc处理静态资源
优雅的rest风格的资源url不希望带.html或.do等后缀,所以在web.xml中配置DispatcherServlet过滤请求时配置的是/,则spring mvc在捕获web容器的所有请求,包括静态资源的请求,如:js时也会将它们当成一个普通的请求处理,因此将不能在controller中找到请求而报404
解决问题:
在spring mvc的配置文件中添加一个<mvc:default-servlet-handler />
原理:
<mvc:default-servlet-handler />将在spring mvc 上下文中定义一个DefaultServletHttpRequestHandler它会对进入DispatcherServlet的请求进行筛查,如果是没有经过映射的请就将该请求交给web应用服务器默认的servlet处理,如果不是静态资源就由DispatcherServlet处理.
注:一般web应用服务器默认的servlet的名称都是default,如使用的web服务器的默认servlet名称不是default,则需要通过default-servlet-name属性显示的指定:
<mvc:default-servlet-handler default-servlet-name="servlet名称" />
Spring mvc 的标签库
Spring mvc没有提供循环的标签,所以如果需要的话还需要使用原生的jstl的c标签
但是spring mvc提供了form标签:
<%@ taglib uri="http://www.springframework.org/tags/form"prefix="form"%>
Form标签可以快速的编写表单页面,并能方便的进行表单数据回显,
注:(spring mvc默认是认为表单是一定需要回显的)可以通过form表示的modelAttribute属性来绑定属性模型,
如果没有绑定,spring mvc默认从request域对象中读取command的表单bean,如果该属性值不存在,则发生异常.
所以modelAttribute属性在表单上不能少,并且需要绑定一个bean,而在表单中的标签的name就是这个bean的属性名称
Java代码:
@RequestMapping("/add")
public String testSessionAttri(Map<String, Object>map) {
map.put("user",user);
return "wel";
}
<form:form action="add" method="post" modelAttribute="数据回显的对象名user">
<form:input path="实体属性名"/>
<form:radiobuttons path="sex" items="${sexMap }"/>
<form:checkbox path="" />
<form:select path="" items="下拉的对象"
itemLabel="下拉的对象名称属性,用于显示" itemValue="选中后获取的值"></form:select>
</form:form>
作业:
用spring mvc ,mysql jsp,jstl,实现一个模块的CRUD,用 restful风格
注:spring mvc在删除的时候需要用post请求方式,因为url默认是get请求,所以需要模拟一个post提交方式,需要借助jquery:
<script type="text/javascript" src="jquery.2.1.js"></script>
<script>
$(function (){
$("#delBtn").click(function (){
var href = $(this).attr("href");
$("#delFormId").attr("action",href).submit();
return false;
});
});
</script>
<form id="delFormId" action="" method="Post">
<input type="hidden" name="_method" value="DELETE">
</form>
<a href="/del/${id}" id="delBtn">删除</a>
mvc:annotation-driven
<mvc:annotation-driven />会自动注册RequestMappingHandlerMapping,RequestMappingHandlerAdapter与ExceptionHandlerExceptionResolver三个bean
还提供以下支持:
支持使用ConversionService实例对表单参数进行类型转换
支持使用@NumberFormatannotation.@DateTimeFormat注解完成数据类型的格式化
支持使用@Valid注解对javabean实例进行jsr 303验证
支持使用@RequestBody和@ResponseBody注解
@InitBinder
由@InitBinder注释的方法可以对WebDataBinder对象进行初始化,WebDataBinder是DataBinder的子类,用于完成表单字段到javaBean属性的绑定
用@InitBinder注释的方法不能有返回值,必须是void的
用@InitBinder注释的方法的参数通常是WebDataBinder
@InitBinder
public void initBinder(WebDataBinderdataBinder){
dataBinder.setAllowedFields("name");
}
使用场景:当添加订单时,表单有一个字段是选择商品,商品是可以选多个的那么这时往往是选中了商品的ID传往后台,而如果是集合或是对像,那么这个时候框架是无法完成在页面选择的是一个ID,
而在后台需要装一个集合或对象的转换的,那么就需要手动转换,那么就用到了@InitBinder注释,表示告诉框架忽略指定字段的转载.
数据格式化和格式化异常消息提示
配置文件复制”spring mvc 注解开发第4点的配置文件”
在前面的例子中的user 类中添加以下 属性:
@DateTimeFormat用于标注在实体类的日期字段上,指定日期的格式,如不标记数据无法获取
@DateTimeFormat(pattern="yyyy-MM-dd")
private Datebirth;
public Date getBirth() {
return birth;
}
public void setBirth(Datebirth) {
this.birth =birth;
}
在前面的例子中的 order类中添加以下 属性:
@NumberFormat用于标注在实体类的浮点字段上,指定浮点的格式,如不标记数据无法获取
@NumberFormat(pattern="#,###,###.#")
private Floatprice;
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price =price;
}
页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
添加订单:<br />
<form action="/springMvcTest/order/add" method="post">
订单名称:<input type="text" name="orderName" /><br />
数量:<input type="text" name="number" /><br />
价格:<input type="text" name="price"/><br />
用户名:<input type="text" name="user.name" /><br />
年龄:<input type="text" name="user.age" /><br />
电话:<input type="text" name="user.tel" /><br />
生日:<input type="text" name="user.birth" /><br />
<input type="submit" value="提交" /><br />
</form>
<br />
</body>
</html>
Controller
@RequestMapping("/add")//请求此方法
public String add(Orderorder,BindingResult bindResult,Modelmodel) {
if (bindResult.getErrorCount() > 0){
System.out.println("转换出错");
for (FieldErrorerror:bindResult.getFieldErrors()){
System.out.println(error.getField()+" : "+error.getDefaultMessage());
}
}
System.out.println(order.toString());
model.addAttribute("msg","添加订单成功 "+order.toString());
return "wel";//视图的名称
}
结果:
转换出错
price : Failed to convert property value of type [java.lang.String] to required type [java.lang.Float] for property 'price'; nested exception isjava.lang.NumberFormatException: For input string: "a"
user.birth : Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'user.birth'; nested exception isorg.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.format.annotation.DateTimeFormat java.util.Date] for value 's'; nested exception isjava.lang.IllegalArgumentException: Parse attempt failed for value [s]
Order [orderName=1, number=1, user=User [id=null, name=1, age=13, tel=1, birth=null]]
Order order,BindingResult bindResult
BindingResult 是框架提供的封装错误信息的处理类,做为参数放在controller类中的处理方法上,并且一定要与实体类参数挨着,
原理:
自定义类型转换器
添加类型转换器:
package com.yirong.controller.annotation;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
@Component
public class OrderConverterimplements Converter<String,Order>{
@Override
public Order convert(Stringsource) {
//逻辑内容,将页面获取的内容封装到order对象中,再把对象返回回去,那么在controller得到的对象就有值
Order order =new Order();
if (null !=source) {
System.out.println(source);
order.setOrderName(source);
}
return order;
}
}
Controller
package com.yirong.controller.annotation;
import java.io.IOException;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("order")
@Controller //表示这个是一个Controller
public class OrderController {
@RequestMapping("/addConverter")//请求此方法
public String add1(@RequestParam("order") Orderorder,Modelmodel ) {
System.out.println(order.toString());
model.addAttribute("msg","添加订单成功 "+order.toString());
return "wel";//视图的名称
}
}
页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
添加订单1:<br />
<form action="/springMvcTest/order/addConverter" method="post">
订单名称:<input type="text" name="order" /><br />
<input type="submit" value="提交" /><br />
</form>
</body>
</html>
配置文件:
<?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-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-lazy-init="true">
<!-- 配置页面渲染器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀 -->
<property name="prefix" value="/"/>
<property name="suffix"value=".jsp"/>
</bean>
<mvc:annotation-driven conversion-service="orderConverterId" />
<mvc:default-servlet-handler/>
<bean id="orderConverterId" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="orderConverter"/> <!--以应转换器的类名,首字母小写-->
</set>
</property>
</bean>
</beans>
JSR 303(数据效验)
添加jsr 303支持jar包
hibernate-validator-5.4.0.Final.jar
hibernate-validator-annotation-processor-5.4.0.Final.jar
classmate-1.3.1.jar
jboss-logging-3.3.0.Final.jar
validation-api-1.1.0.Final.jar
添加配置文件
<?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-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-lazy-init="true">
<!-- 配置页面渲染器 -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 配置结果视图的前缀和后缀 -->
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
<mvc:annotation-driven /> <!-- 基于Schema-based XML的配置定义模式 -->
<context:component-scan base-package="com.yirong.controller" />
<mvc:default-servlet-handler/>
</beans>
User:
package com.yirong.controller.annotation;
import java.util.Date;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
public class User {
private Integerid;
@NotEmpty
private String name;
private Integerage;
private String tel;
@Email(message="邮箱格式错误")
private String email;
@Past //生日应该是一个之前的时间 ,past就表示是之前
@DateTimeFormat(pattern ="yyyy-MM-dd")
private Datebirth;
public Integer getId() {
return id;
}
public void setId(Integerid) {
this.id =id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name =name;
}
public Integer getAge() {
return age;
}
public void setAge(Integerage) {
this.age =age;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel =tel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email =email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Datebirth) {
this.birth =birth;
}
@Override
public String toString() {
return "User [id=" +id +", name=" +name +", age=" + age +", tel=" +tel + ", email=" +email +", birth="
+ birth +"]";
}
}
Controller
package com.yirong.controller.annotation;
import java.io.IOException;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("user")
@Controller //表示这个是一个Controller
public class OrderController {
@RequestMapping("/addUser")//请求此方法
public String add(@Valid Useruser,BindingResultbindResult,Modelmodel) {
if (bindResult.getErrorCount() > 0){
System.out.println("验证异常");
for (FieldErrorerror:bindResult.getFieldErrors()){
System.out.println(error.getField()+" : "+error.getDefaultMessage());
}
}
System.out.println(user.toString());
return "wel";//视图的名称
}
}
页面
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
添加用户 jsr 303:<br />
<form action="/springMvcTest/user/addUser" method="post">
名称:<input type="text" name="name" /><br />
年龄:<input type="text" name="age" /><br />
电话:<input type="text" name="tel" /><br />
生日:<input type="text" name="birth" /><br />
email:<input type="text" name="email" /><br />
<input type="submit" value="提交" /><br />
</form><br /><br />
</body>
</html>
效果:
验证异常
email : 邮箱格式错误
name : 不能为空
birth : 需要是一个过去的时间
User [id=null, name=, age=1, tel=1, email=a, birth=Tue Oct 10 00:00:00 CST 2017]
Json
Spring mvc对json也有很好的支持,需要下载jar
Jackson下载 http://wiki.fasterxml.com/JacksonDownload
导入jar包
jackson-annotations-2.8.0.jar
jackson-core-2.8.1.jar
jackson-databind-2.8.5.jar
配置文件复制”spring mvc 注解开发第4点的配置文件”
页面
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
<script type="text/javascript" src="../jquery-1.10.2.js" ></script>
<script type="text/javascript">
$(function(){
$('#testJsonId').click(function (){
$.post("/springMvcTest/order/testJson",{
},function(data){
console.log(data);
});
});
});
</script>
<br />
testjson:
<button id="testJsonId">testjson</button>
<br />
</body>
</html>
Controlller
package com.yirong.controller.annotation;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("order")
@Controller //表示这个是一个Controller
public class OrderController {
@ResponseBody
@RequestMapping("/testJson")//请求此方法
public List<Order> testJson() {
List<Order> list =new ArrayList<>();
Order o =new Order();
o.setOrderName("a");
Order o2 =new Order();
o2.setOrderName("b");
list.add(o);
list.add(o2);
return list;
}
}
效果:
两个对象的值,正常拿到了
HttpMessageConverter<T>
HttpMessageConverter会将spring mvc框架的返回结果以out对象输出到客户端,只需要加上@responseBody的注解即可自动的用HttpMessageConverter进行转换处理
HttpMessageConverter的@ResponseBody文件上传
Controller
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("order")
@Controller //表示这个是一个Controller
public class OrderController {
@ResponseBody
@RequestMapping("/testh")
public String testh(@RequestBodyStringbody){
System.out.println(body);
return "aa";
}
}
页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
<br />
文件上传:
<form action="/springMvcTest/order/testh" method="POST" enctype="multipart/form-data" >
file:<input type="file" name="file" /><br />
desc:<input type="text" name="desc" /><br />
<input type="submit" value="submit"/>
</form>
<br />
</body>
</html>
运行结果:
响应到页面的文字:
文件下载
在webContent/files/下放一个文件abc.txt,模拟文件下载
Controller
页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>restful</title>
</head>
<body>
<br />
文件下载:
<a href=”testResponseEntity”>test 文件下载</a>
<br />
</body>
</html>
自己写
文件上传和下载
package com.yirong.annoation;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping("/jsr")
public class File {
/**
* 文件上传
* @param desc
* @param file
* @return
*/
@RequestMapping("/uploadFile")
public String uploadFile(@RequestParam("desc") String desc,@RequestParam("file") MultipartFilefile){
System.out.println("文件描述:"+desc);
System.out.println("文件名称:"+file.getOriginalFilename());
try {
InputStream input =file.getInputStream();
BufferedReader buff =new BufferedReader(new InputStreamReader(input));
String str;
System.out.println("文件内容如下:");
while((str =buff.readLine()) !=null){
System.out.println(str);
}
} catch (IOExceptione) {
e.printStackTrace();
}
return "jsr/list";
}
/**
* 文件下载
* @param session
* @return
* @throws IOException
*/
@RequestMapping("/testResponseEntity")
public ResponseEntity<byte[]> restResponseEntity(HttpSessionsession,StringfileName)throws IOException{
byte[]body=null;
String name =new String(fileName.getBytes("iso-8859-1"),"utf-8");
ServletContext context=session.getServletContext();
System.out.println(name);
InputStream in=context.getResourceAsStream("/file/"+name);
body=new byte[in.available()];
in.read(body);
HttpHeaders headers=new HttpHeaders();
headers.add("Content-Disposition","attachment;filename="+new String(name.getBytes(),"iso-8859-1"));
HttpStatus status=HttpStatus.OK;
ResponseEntity<byte[]>response=new ResponseEntity<byte[]>(body,headers,status);
return response;
}
}
页面:
文件上传:
<form action="<%=request.getContextPath()%>/jsr/uploadFile" method="POST" enctype="multipart/form-data" >
file:<input type="file" name="file" /><br />
desc:<input type="text" name="desc" /><br />
<input type="submit" value="submit"/>
</form>
<hr>
<a href="<%=request.getContextPath()%>/jsr/testResponseEntity?fileName=罗.txt">文件下载</a><br/> 要下载的文件必须放置在Webcontent下
<a href="<%=request.getContextPath()%>/jsr/testResponseEntity?fileName=弦子-天真.mp3">弦子 -天真.mp3</a>
<br/>
<hr>
package com.yirong.annoation;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FileUploadController {
/*
* SpringMVC中的文件上传
* @第一步:由于SpringMVC使用的是commons-fileupload实现,故将其组件引入项目中
* @这里用到的是commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar
* @第二步:spring-mvc中配置MultipartResolver处理器。可在此加入对上传文件的属性限制
* <bean id="multipartResolver"
* class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
* <!-- 设置上传文件的最大尺寸为10MB -->
*<property name="maxUploadSize">
*<value>10000000</value>
* </property>
* </bean>
* 第三步:在Controller的方法中添加MultipartFile参数。该参数用于接收表单中file组件的内容
*第四步:编写前台表单。注意enctype="multipart/form-data"以及<input type="file" name="****"/>
* 如果是单个文件 直接使用MultipartFile 即可
*/
@RequestMapping("/upload")
public ModelAndView upload(Stringname,
//上传多个文件
@RequestParam("file") MultipartFile[]file,
HttpServletRequest request)throws IllegalStateException,IOException {
//获取文件 存储位置
String realPath =request.getSession().getServletContext().getRealPath("/uploadFile");
File pathFile =new File(realPath);
if (!pathFile.exists()) {
//文件夹不存 创建文件
pathFile.mkdirs();
}
for (MultipartFilef :file) {
System.out.println("文件类型:"+f.getContentType());
System.out.println("文件名称:"+f.getOriginalFilename());
System.out.println("文件大小:"+f.getSize());
System.out.println(".................................................");
//将文件copy上传到服务器
f.transferTo(new File(realPath +"/" +f.getOriginalFilename()));
//FileUtils.copy
}
//获取modelandview对象
ModelAndView view =new ModelAndView();
view.setViewName("redirect:index.jsp");
return view;
}
@RequestMapping(value ="download")
public ModelAndView download(HttpServletRequestrequest,HttpServletResponseresponse)throws Exception {
//String storeName = "Spring3.xAPI_zh.chm";
String storeName="房地.txt";
String contentType ="application/octet-stream";
FileUploadController.download(request,response,storeName, contentType);
return null;
}
//文件下载 主要方法
public static void download(HttpServletRequestrequest, HttpServletResponseresponse,
String storeName, StringcontentType )throws Exception {
request.setCharacterEncoding("UTF-8");
BufferedInputStream bis =null;
BufferedOutputStream bos =null;
//获取项目根目录
String ctxPath =request.getSession().getServletContext().getRealPath("");
//获取下载文件露肩
String downLoadPath =ctxPath+"/uploadFile/"+storeName;
//获取文件的长度
long fileLength =new File(downLoadPath).length();
//设置文件输出类型
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition","attachment; filename="
+ new String(storeName.getBytes("utf-8"),"ISO8859-1"));
//设置输出长度
response.setHeader("Content-Length", String.valueOf(fileLength));
//获取输入流
bis = new BufferedInputStream(new FileInputStream(downLoadPath));
//输出流
bos = new BufferedOutputStream(response.getOutputStream());
byte[]buff =new byte[2048];
int bytesRead;
while (-1 != (bytesRead =bis.read(buff, 0,buff.length))) {
bos.write(buff, 0,bytesRead);
}
//关闭流
bis.close();
bos.close();
}
}
国际化
在配置文件中添加:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("order")
@Controller //表示这个是一个Controller
public class OrderController {
@Autowired
private ResourceBundleMessageSourcemessageSource;
@RequestMapping("/testI18n")
public String testI18n(Localelocale){
String val =messageSource.getMessage("i18n.username",null,locale);
System.out.println(val);
return "i18n";
}
}
添加配置文件i18n_zh_CN.properties到src下( unicode)
#用户名
i18n.username=\u7528\u6237\u540D
#密码
i18n.password=\u5BC6\u7801
i18n_en_US.properties
i18n.username=username
i18n.password=password
页面相用fmt
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<html>
<head>
<title>springmvc </title>
</head>
<body>
<fmt:message key="i18n.username"></fmt:message>
<br />
<a href="/springMvcTest/order/testI18n" >testI18n </a>
</body>
</html>
效果:
当请求testI18n时,打应的就是资源文件中的相应的国际化资源内容
注:在页面如果需要国际化和数据格式化,则需要用到jstl的fmt标签(spring mvc暂时没有提供标签)
页面中英文切换
页面:
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<html>
<head>
<title>springmvc </title>
</head>
<body>
<fmt:message key="i18n.username"></fmt:message>
<br />
<a href="/springMvcTest/order/testI18n?locale=zh_CH" >testI18n中文</a>
<a href="/springMvcTest/order/testI18n?locale=en_US" >testI18n英文</a>
</body>
</html>
配置文件中添加:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
效果:
Spring mvc文件上传2
导入依赖的jar
commons-fileupload-1.3.1.jar
commons-io-2.2.jar
在配置文件中添加:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<property name="maxUploadSize" value="10240"></property>
</bean>
Controller
@RequestMapping("/testupload")
public String testupload(@RequestParam("desc") String desc,
@RequestParam("file") MultipartFilefile){
System.out.println(desc);
System.out.println(file.getOriginalFilename());
try {
System.out.println(file.getInputStream());
} catch (IOExceptione) {
e.printStackTrace();
}
return "wel";
}
页面添加内容
<br />
文件上传2:
<form action="/springMvcTest/order/testupload" method="POST" enctype="multipart/form-data">
file:<input type="file" name="file" /><br />
desc:<input type="text" name="desc" /><br />
<input type="submit" value="submit"/>
</form>
效果:
自定义拦截器
在spring mvc 框架中要自定义拦截就要实现HandlerInterceptor:
package com.yirong.controller.annotation;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class FirstInterceptorimplements HandlerInterceptor{
/**
* 此方法会在controller的目标方法调用前被调用 ,如果返回false则拦截器的后面两个方法和目标方法都不会再调用,
可以做权限,日志,事务等功能
*/
@Override
public boolean preHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler)
throws Exception {
System.out.println("preHandle ");
return true;
}
/**
* 调用目标方法之后,渲染视图之前被调用 可以对视做出更改,或修改请求域
*/
@Override
public void postHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler,
ModelAndView modelAndView)throws Exception {
System.out.println("postHandle ");
}
/**
* 渲染视图之后被调用 可以做释放资源
*/
@Override
public void afterCompletion(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler, Exceptionex)
throws Exception {
System.out.println("afterCompletion ");
}
}
在配置文件中添加配置
<mvc:interceptors>
<!--自定义拦截器 -->
<bean class="com.yirong.controller.annotation.FirstInterceptor"></bean>
</mvc:interceptors>
写一个controller这里使用JSR 303的例子来调用一下,
访问连接:
http://localhost:8080/springMvcTest/order/addUser
效果:
这样拦截器就已经起效果了
指定url 用指定的拦截器
再创建一个拦截器SecondInterceptor
<mvc:interceptors>
<!--自定义拦截器 -->
<bean class="com.yirong.controller.annotation.FirstInterceptor"></bean>
<mvc:interceptor> <!--表示/addUser 用拦截器:SecondInterceptor-->
<mvc:mapping path="/addUser"/>
<bean class="com.yirong.controller.annotation.SecondInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
Spring mvc拦截器执行顺序:
当后面的拦截器返回false时直接执行前一个拦截器的afterCompletion方法,流程结束
异常处理
DispatcherServlet会默认装配HandlerExceptionResolver,如果spring mvc中没有配置<mvc:annotation-driven/>配置,那么框架会装载:
AnnotationMethodHandlerExceptionResolver,ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver
如果使用了<mvc:annotation-driven/>配置,
那么框架会装载:ExceptionHandlerExceptionResolver,ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver来处理异常
重点:ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver主要用@ExceptionHandler注解定义异常处理方法
@ExceptionHandler定义的异常处理方法有优先级问题,优先使用相对应的异常,如果没有就找抛出的异常的父类,并且不能同时配置多个完全相同的异常处理方法,比如:同时在多个方法标注:@ExceptionHandler({ArrayIndexOutOfBoundsException.class}),或不能同时在多个方法上只标注:@ExceptionHandler
另,如果ExceptionHandlerExceptionResolver在目标controller中找不到@ExceptionHandler注解定义的方法,那么就会去找用@ControllerAdvice注解的类,并找这个类中的用@ExceptionHandler注解的方法来处理异常
注:如果希望将异常显示到页面去,那么只能用ModelAndView,因为用@ExceptionHandler注解的方法不能用Map作为入参
Controller
package com.yirong.controller.annotation;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@RequestMapping("order")
@Controller //表示这个是一个Controller
public class OrderController {
@ExceptionHandler({ArithmeticException.class})
public ModelAndView handlerException(Exceptionex){
System.out.println("异常:"+ex);
ModelAndView mv =new ModelAndView();
mv.setViewName("error");
mv.addObject("exception",ex);
return mv;
}
@ExceptionHandler({RuntimeException.class})
public ModelAndView handlerException1(Exceptionex){
System.out.println("异常1:"+ex);
ModelAndView mv =new ModelAndView();
mv.setViewName("error");
mv.addObject("exception",ex);
return mv;
}
@RequestMapping("/testExcep")
public StringtestExcep(@RequestParam("i") Integeri){
System.out.println(10/i);
return "wel";
}
}
页面添加一个连接
<a href="/springMvcTest/order/testExcep?i=10">异常</a>
当请求此连接,给参数为0的时候,就会出现异常,
出异常的时候,因为有配置@ExceptionHandler,则异常会默认被用此注解的方法去处理
注:@ExceptionHandler可以指定异常的类型,例子中添加了两个异常方法,一个是RuntimeException类型的异常方法,
一个是ArithmeticException类型的异常方法,那么当testExcep方法出异常后会调用被标注为ArithmeticException异常的方法来处理异常,
如果目标controller中没有异常处理方法,那么怎么处理异常?
Spring mvc框架提供了一个异常处理方式,可以将异常处理方法写在一个指定类中,这个类需要用@ControllerAdvice注解,目标controller中没有异常处理方法时,就会找用@ControllerAdvice注解的类,并找这个类中的用@ExceptionHandler注解的方法来处理异常
package com.yirong.controller.annotation;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler({ArithmeticException.class})
public ModelAndView handlerException(Exceptionex){
System.out.println("异常:"+ex);
ModelAndView mv =new ModelAndView();
mv.setViewName("error");
mv.addObject("exception",ex);
return mv;
}
@ExceptionHandler({RuntimeException.class})
public ModelAndView handlerException1(Exceptionex){
System.out.println("异常1:"+ex);
ModelAndView mv =new ModelAndView();
mv.setViewName("error");
mv.addObject("exception",ex);
return mv;
}
}
SimpleMappingExceptionResolver
了解
SimpleMappingExceptionResolver异常处理,ex为页面使用的对象在requestScope中
prop 表示配置发生指定异常去指定页面
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionAttribute" value="ex"></property>
<property name="exceptionMappings">
<props>
<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
</props>
</property>
</bean>
SpringMVC数据转换 & 数据格式化 & 数据校验
Spring mvc 整合spring
使用注解,那么就需要在配置文件中配置扫描<context:component-scan base-package="指定扫描的包路径" />
Spring mvc需要配置,而spring的容器也需要配置,也就是配置bean的包.如果这两个配置有重复的话,那么容器将加载多次,这是不对的.
所以需要配置过滤:
在spring mvc的配置文件中可以配置指定要扫描的包路径下的指定注解,在spring 中可以配置指定路径下不扫描指定注解
<context:component-scan base-package="com.yr" use-default-filters="false" >
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
Spring配置文件中:
<context:component-scan base-package="com.yr" use-default-filters="false" >
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
- springmvc 从入门到总结
- SpringMVC从入门到精通
- springmvc从入门到精通
- SpringMVC从入门到精通(一)
- SpringMVC从入门到精通(二)
- SpringMVC从入门到精通(一)
- SpringMVC从入门到精通(二)
- struts2 从入门到总结
- spring 从入门到总结
- mybatis 从入门到总结
- docker_practice从入门到实践总结
- 推送,从入门到放弃 笔记总结
- hibernate4.1.1 从入门到总结
- SpringMVC从入门到精通(终结版)
- SpringMVC从入门到精通之第一章【转】
- SpringMVC从入门到精通之第二章【转】
- SpringMVC从入门到精通之第三章【转】
- SpringMVC从入门到精通之第四章【转】
- mysql generator使用方法
- linux 下性能分析工具 Gprof
- 解决supervisord进程导致的队列时差问题
- cocos内存管理机制
- SDN开发笔记:md-sal应用程序开发
- springmvc 从入门到总结
- Spring+SpringMVC+hibernate spatial+oracle spatial 映射存储Geomety空间数据过程记录
- .net MVC前后端通信—SingleR,文件监控FileSystemWatcher
- 第一课:慕课网Vue.js音乐播放器
- 剑指offer 从上往下打印二叉树
- MySQL之进行行列转换
- Android TextView使用HTML处理字体样式、显示图片等
- LeetCode 191. Number of 1 Bits
- .net 实现http下载