SpringMVC
一.SpringMvc的Helloworld,一个SpringMvc实例的简单流程
1.在web.xml文件中配置DispacherServlet:配置SpringMvc配置文件的位置和名称
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置DispatcherServlet的初始化参数:SpringMvc配置文件的位置和名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.创建springMvc配置文件,根据web.xml文件中的配置。配置文件名为:springMvc.xml,位于src路径下
1).自动扫描的包在spring中有相关介绍,此处不做介绍
2).配置视图解析器:为了将handler方法的返回值解析为实际的物理视图,此处为解析成jsp。
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="springmvc.helloworld"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
3.使用@RequestMapping映射请求
1).使用@RequestMapping注解映射请求的URL
2).返回值(此处为“success”)会通过视图解析解析为实际的物理视图,此处为InternalResourceViewResolver,并
通过prefix + 返回值 + suffix 这样的方式得到实际的物理视图,然后做转发操作
@Controller
public class HelloWorld {
@RequestMapping("/helloWorld")
public String hello(){
System.out.println("helloWorld");
return "success";
}
}
4.两个jsp页面
1).首页(index.jsp)
<body>
<a href="helloWorld">To success</a>
</body>
2).目标页面(success.jsp),注意:根据视图解析器中的配置,success.jsp位于/WEB-INF/views目录下
<body>
<h1>Hello!</h1>
</body>
5.现象:进入index.jsp页面后,点击超链接,则可进入success.jsp页面
二、使用@RequestMapping映射请求
1.SpringMvc使用@RequestMapping注解为控制器指定可以处理的URL请求,注解可以标记在类上或方法上
2.Dispatcher截获请求后就通过@RequestMapping提供的映射信息确定请求所对应的处理方法
3.@RequestMapping中可以指定value(请求URL)、method(请求的方法)、params(请求参数)、heads(请求头),他们之间时 与的关系,使用多个条件联合查询,可使请求精确化。
4.支持Ant风格的Url,Ant风格地址支持三种匹配符: ?:匹配文件名中的一个字符
*:匹配文件名中的任意字符
**:** :匹配多层路径
5.@PathVariable映射URL绑定的占位符
通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中
请求的URL为:<a href="helloworld/1">To success</a> ,可将“1”传入到方法中
@RequestMapping("/helloworld/{id}")
public String hello(@PathVariable("id") Integer id){
System.out.println("helloWorld"+id);
return "success";
}
三、映射请求参数、请求头
SpirngMvc通过分析处理方法的签名,将Http请求信息绑定到处理方法的相关入参中
1.使用@RequestParam可以把请求参数传递给请求方法 value:参数名、required:是否必须
请求Url:<a href="helloworld?username=123">To success</a>,可将请求参数中的“123”传递给方法。
@RequestMapping("/helloworld")
public String hello(@RequestParam(value="username" required=false) String un){
System.out.println("helloWorld:"+un);
return "success";
}
2.使用@RequestHeader绑定请求报头信息,请求头包含了若干属性,服务器可据此获知客户端的信息。
@RequestMapping("/helloworld")
public String hello(@RequestHeader("Accept-Encoding") String encoding){
System.out.println("helloWorld:"+encoding);
return "success";
}
3.使用@CookieValue绑定请求中的Cookie值
@RequestMapping("/helloworld")
public String hello(@CookieValue("JSESSIONID") String sessionId){
System.out.println("helloWorld:"+sessionId);
return "success";
}
4.使用POJO对象绑定请求参数,SpirngMvc会按照请求参数名和POJO属性名自动进行匹配,自动为该对象填充属性,支持级联属性
1).表单,此表单对应一个User的JavaBean
<form action="testPojo" method="post">
username:<input type="text" name="username"> <br>
password:<input type="password" name="password"> <br>
age:<input type="text" name="age"><br>
<input type="submit" name="Submit">
</form>
2).处理方法,,结果会在控制输出user: User [username=adfd, password=585, age=13]
@RequestMapping("/testPojo")
public String testPojo(User user) {
System.out.println(user);
return "success";
}
5.MVC的Handler可以接收ServletAPI
HttpServletRequest、HttpServletResponse、HttpSession、java.security.Principal、Locale、InputStream、OutputStream
Reader、Writer
四、处理模型数据
1.ModelAndView
控制器处理方法的返回值可以是ModelAndView,其包含模型和数据信息,Springmvc会将model中的数据放到request域中。
添加模型数据: ModelAndView addObject(String attributeName,Object attributeValue)
ModelAndView addAllObject(Map<String,?> modelMap)
设置视图: void setView(View view)
void setViewName(String ViewName)
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
ModelAndView mv = new ModelAndView("success");
mv.addObject("time", new Date());
return mv;
}
可在目标页面success.jsp接收time:
time:<%=request.getAttribute("time") %>
2.Map及Model 也可以传入Map和Model类型,目标方法可以添加Map类型(也可以是Model类型或是ModelMap类型参数)
@RequestMapping("testMap")
public String testMap(Map<String, Object> map) {
map.put("names", Arrays.asList("Li","Wu","Zhang"));
return "success";
}
同样可在目标页面success.jsp接收到names参数
names:<%=request.getAttribute("names") %>
-
@SessionAttributes 注意:此注解只能放在类上
若希望在多个请求之间共用某个模型参数,则可以在控制器类上标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂 存到HttpSession中。
value属性:通过属性名指定需要放到会话中的属性 types属性:通过模型属性的对象类型指定哪些模型属性需要放到会话中
@SessionAttributes(value= {"user"},types= {String.class})
@Controller
public class HelloWorld {
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Map<String, Object> map) {
User user = new User("Li", "123456", 24);
map.put("user", user);
return "success";
}
}
可在目标页面的session域中得到user
user:<%=session.getAttribute("user") %>
-
@ModelAttribute @ModelAttribute 标记的方法, 会在每个目标方法执行之前被 SpringMVC 调用!
ModelAttribute的典型应用:模拟修改操作
运行流程:*执行 @ModelAttribute注解修饰的方法:从数据库中取出对象,把对象放入到Map中,键为user
**SpringMVC从Map中取出User对象,并把表单的请求参数赋给User对象的对应属性值。 ***SpringMVC把上述对象传入目标方法的参数。
1).表单
<!--
模拟修改操作:
1.原始表单为:1,Tom,123456,24
2.密码不能被修改
3。表单回显,模拟操作直接在表单上填写对应属性值
-->
<form action="testModelAttribute" method="post">
<input type="hidden" name="id" value="1">
username:<input type="text" name="username" value="Tom"> <br>
age:<input type="text" name="age" value="24"><br>
<input type="submit" name="Submit">
</form>
2).主方法
@ModelAttribute
public void getUser(@RequestParam(value="id") Integer id,Map<String,Object> map) {
if(id!=null) {
User user = new User(1, "Tom", "123456", 24);
System.out.println("从数据库中取出:"+user);
map.put("user", user);
}
}
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("修改:" + user);
return "success";
}
3).结果
如若在表单中将修改age或是username,都将修改成功,其余值不变
五、视图及视图处理器
1.SpringMVC如何解析视图:
对于那些返回String、view或ModelMap等类型的处理方法,SpringMvc都会将其装配成一个ModelAndView对象。view接口时无状 态的,不会有线程安全问题
2.重定向
如果返回的字符串中带有“forward:”或“redirect:”前缀时,SpringMVC会对他们进行特殊处理,将其当成指示符,其后的字符串
作为URL来处理。
六、数据的转换、格式化、校验
1.数据转换
SpringMVC定义了3种类型的转换器接口:
* Converter<S,T>:将S类型转换为T类型对象
* ConverterFactory:将相同系列多个“同质”Conterver封装在一起
* GenericConverter: 会根据源类对象及目标所在的宿主主类中的上下文信息进行类型转换
实例如下:
1)表单
<form action="testConverter" method="POST">
<!-- 格式例如:Harry-123456-24 -->
Employee:<input type="text" name="user">
<input type="submit" name="Submit">
</form>
2).转换器
@Component
public class UserConverter implements Converter<String, User> {
@Override
public User convert(String source) {
if(source != null) {
System.out.println("aa");
String[] vals = source.split("-");
if(vals != null) {
String username = vals[0];
String password = vals[1];
String age = vals[2];
User user = new User(username, password, Integer.parseInt(age));
System.out.println("converter:"+user);
return user;
}
}
return null;
}
}
3).配置文件
<mvc:annotation-driven conversion-service="converterService"></mvc:annotation-driven>
<!-- 配置converterService -->
<bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="userConverter"/>
</set>
</property>
</bean>
4).目标方法
@RequestMapping("/testConverter")
public String testConverter(@RequestParam("user") User user) {
System.out.println(user);
return "success";
}
2.数据格式化
1).在配置文件中添加上<mvc:annotation-driven ></mvc:annotation-driven>
2).在目标类型的属性上配置
@NumberFormat(pattern="#.###")
private double price;
@DateTimeFormat(pattern="yyyy-mm-dd")
private Date birth;
3.数据的校验
1).使用 JSR 303 验证标准,在 SpringMVC 配置文件中添加 <mvc:annotation-driven />,<mvc:annotation-driven />会默认装配好一个 LocalValidatorFactoryBean。
2).需要在 bean 的属性上添加对应的注解
例如:@NotNull :被注释的元素不能为空 @Past :备注是的元素必须是一个过去的日期
@Email :被注释的元素必须是一个email
3). 在目标方法 bean 类型的前面添加 @Valid 注解
七、文件上传
SpringMvc通过MutipartResolver实现文件上传
1.配置MutipartResolver
<!-- 配置 MultipartResolver -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="1024000"></property>
</bean>
2.表单
<form action="testFileUpload" method="POST" enctype="multipart/form-data">
File: <input type="file" name="file"/>
Desc: <input type="text" name="desc"/>
<input type="submit" value="Submit"/>
</form>
3.目标方法
@RequestMapping("/testFileUpload")
public String testFileUpload(@RequestParam("desc") String desc,
@RequestParam("file") MultipartFile file) throws Exception {
System.out.println("InputStream:" + file.getInputStream());
return "success";
}
八、使用拦截器
SpringMvc也可以使用拦截器对请求进行拦截,可以自定义拦截器来实现特定的功能,自定义拦截器必须实现HandlerInterceptor接口
1.实现HandlerInterceptor接口的拦截器类
public class FirstInterceptor implements HandlerInterceptor {
/**
* 渲染视图之后被调用. 释放资源
*/
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("afterCompletion");
}
/**
* 调用目标方法之后, 但渲染视图之前.
* 可以对请求域中的属性或视图做出修改.
*/
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("postHandle");
}
/**
* 该方法在目标方法之前被调用.
* 若返回值为 true, 则继续调用后续的拦截器和目标方法.
* 若返回值为 false, 则不会再调用后续的拦截器和目标方法.
*
* 可以考虑做权限. 日志, 事务等.
*/
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("preHandle");
return true;
}
}
2.配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<bean class="springmvc.helloworld.FirstInterceptor"></bean>
</mvc:interceptors>