对于SpringMVC来说,controller由两个部分构成,分别是分发器和控制器,分发器DispatcherServlet决定着请求使用哪个控制器,并且决定着控制器返回哪个视图,整体结构如下.
1.创建一个controller
对于DispatcherServlet这个是springMVC框架自动实现,而我们只需要写相应的控制器即可,就拿上一个helloworld例子来说,创建一个控制器,只需要给其加上@controller的注解
/**
* 加上@Controller决定这个类是一个控制器
*/
@Controller
public class HelloController {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello";
}
}
@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器,这个接下来就会讲到。
让控制器起作用,则需要在springMVC.xml配置文件中配置,也就是上一篇搭建基本环境中的配置
2.让controller返回一个jsp视图
@RequestMapping 注解决定着返回的jsp视图,对于这个属性先简单来说一般配置value和method两个值,value决定着请求的路径,method决定着请求的方法
@Controller
public class HelloController {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello";
}
}
拿上面例子来说,直接在浏览器访问localhost:8888/hello即可访问到这个控制器,对应的请求为GET请求,此方法返回一个hello字符串,说明对应的视图为hello.jsp,这是最简单的访问形式,如果我们想要传值的话,该怎么做呢?
- 方法1:在参数中加一个model,直接把值放进去就可以了
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(Model model){
// 这样放参数的话,在jsp中直接用EL访问hello即可
model.addAttribute("hello","world1");
// 这样方参数的话,默认的key是参数类型
model.addAttribute("world2");
return "hello";
}
在对应的jsp中可以如下获取
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1 style="text-align: center">Hello World!${hello}----${string}</h1>
</body>
</html>
- 方法2;使用ModelAndView
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public ModelAndView hello(){
ModelAndView model = new ModelAndView();
//设置返回视图名称
model.setViewName("hello");
//传值,规则同上
model.addObject("hello","world1");
//传值,规则同上
model.addObject("world2");
return model;
}
两种方法几乎没区别,根据爱好使用.
3.使用URI模板
URI模板是用来获取url中的值,看下面小例子
@RequestMapping(value = "/hello/{id}",method = RequestMethod.GET)
public String hello(@PathVariable("id") String id, Model model){
// 这样放参数的话,在jsp中直接用EL访问hello即可
model.addAttribute("hello",id);
return "hello";
}
上面在value = “/hello/{id}”,说明访问的url必须为/hello/XX这样的链接,@PathVariable(“id”) String id,的作用就是把这个XX放入id中,然后jsp页面就可以获取这个值了
除此之外还支持*通配符访问
@Controller
@RequestMapping ( "/myTest" )
public class MyController {
@RequestMapping ( "*/wildcard" )
public String testWildcard() {
System. out .println( "wildcard------------" );
return "wildcard" ;
}
}
那么此时的访问路径只要为/mytest/**/wildcard都可以访问当前连接
4.@RequestParam 绑定 HttpServletRequest 请求参数
对于请求名和属性名一致的,springmvc会默认自动绑定,对于不一致的需要使用RequestParam 来进行映射
@RequestMapping ( "requestParam" )
public String testRequestParam( @RequestParam(required=false) String name, @RequestParam ( "age" ) int age) {
return "requestParam" ;
}
requird=false代表name是非必须值,可以不存在HttpServletRequest 之中,而后面的age则不同,要求必须在HttpServletRequest 之中,否则会报错.
值得注意的是和@PathVariable 一样,当你没有明确指定从request 中取哪个参数时,Spring 在代码是debug 编译的情况下会默认取更方法参数同名的参数,如果不是debug 编译的就会报错。此外,当需要从request 中绑定的参数和方法的参数名不相同的时候,也需要在@RequestParam 中明确指出是要绑定哪个参数。
类似的还有@CookieValue,@RequestHeader都类似用法,不过一般不用这种方法,接着看下面RequestMapping 的高级用法.
5.RequestMapping 的高级用法
1.支持的方法参数类型
- HttpServlet 对象,主要包括HttpServletRequest 、HttpServletResponse 和HttpSession 对象。 这些参数Spring 在调用处理器方法的时候会自动给它们赋值,所以当在处理器方法中需要使用到这些对象的时候,可以直接在方法上给定一个方法参数的申明,然后在方法体里面直接用就可以了。但是有一点需要注意的是在使用HttpSession 对象的时候,如果此时HttpSession 对象还没有建立起来的话就会有问题。
- Spring 自己的WebRequest 对象。 使用该对象可以访问到存放在HttpServletRequest 和HttpSession 中的属性值。
- InputStream 、OutputStream 、Reader 和Writer 。 InputStream 和Reader 是针对HttpServletRequest 而言的,可以从里面取数据;OutputStream 和Writer 是针对HttpServletResponse 而言的,可以往里面写数据。
- 使用@PathVariable 、@RequestParam 、@CookieValue 和@RequestHeader 标记的参数。
- 使用@ModelAttribute 标记的参数。
- java.util.Map 、Spring 封装的Model 和ModelMap 。 这些都可以用来封装模型数据,用来给视图做展示。
- 实体类。 可以用来接收上传的参数。
- Spring 封装的MultipartFile 。 用来接收上传文件的。
- Spring 封装的Errors 和BindingResult 对象。 这两个对象参数必须紧接在需要验证的实体对象参数之后,它里面包含了实体对象的验证结果。
2.支持的返回类型
- 一个包含模型和视图的ModelAndView 对象。
- 一个模型对象,这主要包括Spring 封装好的Model 和ModelMap ,以及java.util.Map ,当没有视图返回的时候视图名称将由RequestToViewNameTranslator 来决定。
- 一个View 对象。这个时候如果在渲染视图的过程中模型的话就可以给处理器方法定义一个模型参数,然后在方法体里面往模型中添加值。
- 一个String 字符串。这往往代表的是一个视图名称。这个时候如果需要在渲染视图的过程中需要模型的话就可以给处理器方法一个模型参数,然后在方法体里面往模型中添加值就可以了。
- 返回值是void 。这种情况一般是我们直接把返回结果写到HttpServletResponse 中了,如果没有写的话,那么Spring 将会利用RequestToViewNameTranslator 来返回一个对应的视图名称。如果视图中需要模型的话,处理方法与返回字符串的情况相同。
- 如果处理器方法被注解@ResponseBody 标记的话,那么处理器方法的任何返回类型都会通过HttpMessageConverters 转换之后写到HttpServletResponse 中,而不会像上面的那些情况一样当做视图或者模型来处理。
- 除以上几种情况之外的其他任何返回类型都会被当做模型中的一个属性来处理,而返回的视图还是由RequestToViewNameTranslator 来决定,添加到模型中的属性名称可以在该方法上用@ModelAttribute(“attributeName”) 来定义,否则将使用返回类型的类名称的首字母小写形式来表示。使用@ModelAttribute 标记的方法会在@RequestMapping 标记的方法执行之前执行。
对于方法参数,就像使用Model传值一样,可以直接在参数中加入req,resp,session等,然后就像servlet那样使用就可以了
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(Model model, HttpServletRequest request, HttpServletResponse response, HttpSession session){
// 这样放参数的话,在jsp中直接用EL访问hello即可
return "hello";
}
6.定义自己的转换器
在通过处理器方法参数接收 request 请求参数绑定数据的时候,对于一些简单的数据类型 Spring 会帮我们自动进行类型转换,而对于一些复杂的类型由于 Spring 没法识别,所以也就不能帮助我们进行自动转换了,这个时候如果我们需要 Spring 来帮我们自动转换的话就需要我们给 Spring 注册一个对特定类型的识别转换器。 Spring 允许我们提供两种类型的识别转换器,一种是注册在 Controller 中的,一种是注册在 SpringMVC 的配置文件中。聪明的读者看到这里应该可以想到它们的区别了,定义在 Controller 中的是局部的,只在当前 Controller 中有效,而放在 SpringMVC 配置文件中的是全局的,所有 Controller 都可以拿来使用。
- 局部转换器
@InitBinder
public void initBinder(WebDataBinder binder){
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
PropertyEditor propertyEditor = new CustomDateEditor(format, true ); // 第二个参数表示是否允许为空
binder.registerCustomEditor(Date.class, propertyEditor);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 全局转换器
public class MyWebBindingInitializer implements WebBindingInitializer {
@Override
public void initBinder(WebDataBinder binder, WebRequest request) {
// TODO Auto-generated method stub
DateFormat dateFormat = new SimpleDateFormat( "yyyyMMdd" );
PropertyEditor propertyEditor = new CustomDateEditor(dateFormat, true );
binder.registerCustomEditor(Date. class , propertyEditor);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
需要在springMVC.xml中引入这个转换器
< bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
< property name = "webBindingInitializer" >
< bean class = "com.host.app.web.util.MyWebBindingInitializer" />
</ property >
</ bean >
- 1
- 2
- 3
- 4
- 5
剩下的用法没区别了