先配置 springmvc.xml:
<!-- 扫描有注解的包 -->
<context:component-scan base-package="org.lanqiao.handler">
</context:component-scan>
<!-- 配置视图解析器(InternalResourceViewResolver) -->
<!-- 前缀为/views/,后缀为.jsp,拼接成目标jsp的位置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
使用Alt+/ ,选中内容后自动生成servlet的配置信息。
生成内容稍作修改后如下:
指定 < param-value >
设置 < url-pattern >
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</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>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
其中的 < url-pattern >/< /url-pattern >拦截范围设置:
/: 拦截一切请求,注意不是 /*
/user: 拦截以 /user开头的请求
/user/abc.do : 只拦截特定的请求
.action: 只拦截 .action结尾的请求
Handler 代码
@Controller
@RequestMapping("aaa")
public class SpringMVCHandler {
@RequestMapping("test")
public String test() {
//拼接为 /views/success.jsp,从而访问到success.jsp
return "success";
}
}
index.jsp 中的表单代码:
映射过程:先找到前面的aaa,然后找到test
<form action="aaa/test">
name:<input name="uname" type="text"> <br>
age:<input name="uage" type="text"> <br>
<input type="submit" value="查">
</form>
method 指定 请求方式(get post delete put)
@RequestMapping(value="welcome",method=RequestMethod.POST)//映射
? 单字符
* 任意个字符(0或多个)
** 任意目录
例:@RequestMapping(value="welcome3/**/test")
接受示例:a href="welcome3/abc/xyz/abccc/test"
接收请求路径中占位符的值(例如此时的23),获取动态参数
<form action="aaa/test/23">
<input type="submit" value="查">
</form>
@Controller
@RequestMapping("aaa")
public class SpringMVCHandler {
@RequestMapping("test/{age}") //把23先放入age
public String test(@PathVariable("age") String age) {
System.out.println(age); //输出age的值,为23
return "success";
}
}
Springmvc:
GET :查
POST :增
DELETE :删
PUT :改
普通浏览器 只支持get post方式 ;其他请求方式 如 delelte/put请求是通过 过滤器 新加入的支持。
a.增加过滤器
<!-- 增加HiddenHttpMethodFilte过滤器:目的是给普通浏览器 增加 put|delete请求方式 -->
<filter>
<filter-name>HiddenHttpMethodFilte</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilte</filter-name>
<url-pattern>/*
b.表单
<form action="handler/testRest/1234" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="删">
</form>
c.控制器
@RequestMapping(value="testRest/{id}",method=RequestMethod.DELETE)
public String testDelete(@PathVariable("id") Integer id) {
System.out.println("delete:删 " +id);
//Service层实现 真正的增
return "success" ;// views/success.jsp,默认使用了 请求转发的 跳转方式
}
//通过 method=RequestMethod.DELETE 匹配具体的请求方式
必须注意两点:测试接收uname的值
<form action="aaa/test">
name:<input name="uname" type="text"> <br>
<input type="submit" value="查">
</form>
@Controller
@RequestMapping("aaa")
public class SpringMVCHandler {
@RequestMapping("test")
public String test(@RequestParam("uname") String name) {
System.out.println(name);
return "success";
}
}
等价于:name = request.getParameter("uname")
实体类 Student 属性:
private int id;
private String name;
private Address address;
实体类 Address 属性:
private String homeAddress;
private String schoolAddress;
表单内容(将name与student的属性对应):
<form action="aaa/test">
id:<input name="id" type="text"> <br>
name:<input name="name" type="text"> <br>
homeAddress:<input name="address.homeAddress" type="text"> <br>
schoolAddress:<input name="address.schoolAddress" type="text"> <br>
<input type="submit" value="查">
</form>
把输入的结果存入stu,并打印结果:
@RequestMapping("test")
public String test(Student stu) {
System.out.println(stu.getId()+" "+stu.getName()+" "+stu.getAddress().getHomeAddress()+" "+stu.getAddress().getSchoolAddress());
return "success";
}
HttpServletRequest :直接将 servlet-api中的类、接口等 写在springMVC所映射的方法参数中即可:
@RequestMapping(value="testServletAPI")
public String testServletAPI(HttpServletRequest request,HttpServletResponse response) {
request.getParameter("uname") ;
System.out.println(request);
return "success" ;
}
<form action="aaa/xxx">
id:<input name="id" type="text"> <br>
name:<input name="name" type="text"> <br>
<input type="submit" value="查">
</form>
再springmvc.xml配置中加入以下配置,即可实现两个jsp的直接跳转(不通过控制器):
<mvc:view-controller path="aaa/*" view-name="success"/>
以上配置 ,会让所有的请求 转入mvc:..中匹配映射地址,而会忽略调@RequsetMapping();
//此配置是SpringMVC的基础配置,很多功能都需要通过该注解来协调
<mvc:annotation-driven></mvc:annotation-driven>
forward(请求转发): redirect(重定向): ,但是此种方式,不会被视图解析器加上前缀(/views)、后缀(.jsp)
例如:return “forward:/views/success.jsp”;
访问 WebContent 目录下的1.png 时
http://localhost:8888/SpringMVCProject/1.png
此时无法访问的原因是:SpringMVC在访问时,默认通过@RequestMapping() 去寻找 1.png,找不到时,就报404
因此,在 springmvc.xml 中 加入以下配置即可正常访问
<!-- 该注解会让springmvc:接收一个请求,并且该请求
没有对应的@requestmapping时,将请求交给默认的servlet(直接访问) -->
<mvc:default-servlet-handler/>
总结:要让springmvc访问静态资源,只需要加入以下2个注解:
// 前面用到的
此配置是SpringMVC的基础配置,很多功能都需要通过该注解来协调
< mvc:annotation-driven></mvc:annotation-driven>
</mvc:default-servlet-handler>
@DateTimeFormat(pattern="yyyy-MM-dd") //格式化 Date类型
@NumberFormat(parttern="###,#") //格式化 数字类型(输入123,4 格式化为1234)
首先,需要在springmvc.xml中加入配置:
<!-- 配置 数据格式化 注解所依赖的bean -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"></bean>
在变量上方写注解
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date bir;
@RequestMapping("test1")
public String test1(Student stu,BindingResult result) {
//stu传值时出现错误,则存入后面的参数result中
System.out.println(stu.getId());
System.out.println(stu.getName());
System.out.println(stu.getBir());
System.out.println(result);
return "forward:/views/success.jsp";
}
放入request域中的几个方法:
ModelMap 、Map、Model -数据放在了request作用域
此处使用map测试:
@RequestMapping("test1")
public String test1(Student stu,BindingResult result,Map<String,Object> map) {
//ps:result的位置必须睡觉哦stu后面一个参数,才能接收到错误,否则报错
System.out.println(stu.getId());
System.out.println(stu.getName());
System.out.println(stu.getBir());
System.out.println(result);
map.put("errors", result); //以key-value形式 放入request域中
return "success";
}
在success.jsp使用:
${
requestScope.errors } //在jsp中展示错误信息
导 jar 包:
① hibernate-validator-5.0.0.CR2.jar
② classmate-0.8.0.jar
③ validation-api-1.1.0.CR1.jar
④ hibernate-validator-annotation-processor-5.0.0.CR2.jar
⑤ jboss-logging-3.1.1.GA.jar
第一步 @Past:
@Past //需要输入一个过去的日期
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date bir;
第二步 (加@Valid):
// 在接收的stu前加上 @Valid 注解
public String test1(@Valid Student stu,BindingResult result,Map<String,Object> map)
( SpringMVC可以简化文件上传的代码,但是必须满足条件:实现 MultipartResolver接口 ;而该接口的实现类SpringMVC也已经提供了CommonsMultipartResolver )
首先,添加 jar 包:
commons-fileupload.jar
commons-io.jar
配置 SpringMVC.xml :
<!-- 配置 文件上传 所依赖的bean,此时id必须为multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 上传单个文件的最大值,单位Byte;如果-1,表示无限制 -->
<property name="maxUploadSize" value="-1"></property>
</bean>
表单内容(文件上传)
method="post" enctype="multipart/form-data"
<form action="aaa/testFileUpload" method="post" enctype="multipart/form-data">
上传描述:<input name="desc" type="text"><br>
<input name="file" type="file">
<input type="submit" value="上传">
</form>
实现文件上传的代码:
@RequestMapping("testFileUpload")
public String testFileUpload(@RequestParam("desc") String desc,@RequestParam("file") MultipartFile file) throws IOException {
InputStream in = file.getInputStream();
//存入d盘目录下,文件名为原始文件名
OutputStream out = new FileOutputStream("d://"+file.getOriginalFilename());
//字节流方式
byte[] b = new byte[1024];
int len=0;
while( (len = in.read(b)) !=-1) {
out.write(b,0,len);
}
out.close();
in.close();
System.out.println("文件描述: " + desc);
System.out.println("文件上传成功!!!");
return "success";
}
SpringMVC:要想实现拦截器,必须实现一个接口HandlerInterceptor
编写一个拦截器:
// 实现 HandlerInterceptor接口,并重写三个方法
public class MyInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("视图(jsp)渲染完毕");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("拦截响应!!!");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("拦截请求!!!");
return true; //true代表拦截后放行,false代表拦截后不放行(即请求终止)
}
}
在springmvc.xml中配置:
<!-- 将自己写的拦截器 配置到springmvc中,默认拦截全部请求 -->
<mvc:interceptors>
<bean class="org.lanqiao.Interceptor.MyInterceptor"></bean>
</mvc:interceptors>
(倘若不拦截全部请求,可以设置拦截的路径和不拦截的路径)
<!-- 将自己写的拦截器 配置到springmvc中,默认拦截全部请求 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 指定拦截的路径 -->
<mvc:mapping path=""/>
<!-- 指定不拦截的路径 -->
<mvc:exclude-mapping path=""/>
<bean class="org.lanqiao.Interceptor.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
@ControllerAdvice //该注解支持捕获其它类中的异常
public class MyExceptionHandler {
@ExceptionHandler({
Exception.class}) //捕获所有类型异常
public ModelAndView Exception(Exception e) {
ModelAndView mView = new ModelAndView("error");
mView.addObject("er",e); //放入request域中
return mView;
}
}
@RequestMapping("testHandler")
public void testHandler() throws MyExceptionHandler {
throw new MyExceptionHandler(); //抛出异常
}
//value为状态码,reason为异常信息
@ResponseStatus(value=HttpStatus.BAD_REQUEST,reason="测试异常")
public class MyExceptionHandler extends Exception{
//自定义异常
}