3.2.3 SpringMVC注解式开发

时间:2023-03-09 01:39:37
3.2.3 SpringMVC注解式开发

SpringMVC注解式开发

1. 搭建环境

(1) 后端控制器无需实现接口 , 添加相应注解

Controller类添加注解

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用,命名空间

public class MyController{

@RequestMapping("/hadleRequest")  //设定方法访问的映射路径

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

ModelAndView mv = new ModelAndView();

System.out.println("进入到后端控制器方法!");

mv.addObject("msg", "Hello SpringMVC!");

mv.setViewName("/jsp/welcome.jsp");

return mv;

}

}

 

访问的路径有类体上的请求映射路径和方法体上的请求映射路径共同组成,则springmvc/hadleRequest。

 

(2) springmvc配置文件无需注册controller

springmvc.xml中,把

<bean id="/my.do" class="com.mypack.handler.Mycontroller"></bean>

这句去掉。

(3) springmvc配置文件中添加组件扫描器、 注解驱动

Springmvc.xml中添加,把包名复制到base-pakage之后

<!-- 注册组件扫描器 -->

<context:component-scan base-package="com.mypack.handlers"></context:component-

scan>

<!-- 注册注解驱动,自动注册处理器映射器,和处理适配器这两个对象 -->

<mvc:annotation-driven/>

2. 涉及常用注解

@Controller:类和方法都可用

@RequestMapping:类体上, 命名空间, 方法上

@Scope:bean的作用域

3. 视图解析器( 前缀、 后缀)

<!-- 注册视图解析器 查找InternalResourceViewResolver得到完全类名-->

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix" value="/jsp/"></property>

<property name="suffix" value=".jsp"></property>

</bean>

底层是纯粹的字符串拼接,当你返回一个视图资源的时候,它会找你是否配置了视图解析器,会把你的前缀+视图名+后缀,组成完成路径。

4. 处理器方法常用的参数( 五类)

(1) HttpServletRequest:请求对象

(2) HttpServletResponse:响应对象

(3) HttpSession:会话对象

(4) 用于承载数据的Model、 Map、 ModelMap

(5) 请求中所携带的请求参数

5. 接收请求参数

(1) 逐个接收 (涉及注解@RequestParam)

有几个参数接收几个。

jsp提交2个参数:

<form action="springmvc/hello" method="POST">

<input type="text" name="username"></br>

<input type="text" name="age"></br>

<input type="submit" value="提交">

</form>

MyController接收

public class MyController{

@RequestMapping("/hello")

public ModelAndView hello(String username,int age){

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("username", username);

modelAndView.addObject("age", age);

modelAndView.setViewName("welcome");

return modelAndView;

}

}

 

welcome.jsp打印

欢迎页面!${username}--${age}

接收前提,传过来的参数name值,和处理器方法的参数名,必须一致,不然接收不到。name值和方法参数不同,要用@RequestParam注解注明,起到参数校正的作用

@RequestParam("username") String name,int age

(2) 以对象形式整体接收

创建一个类

public class Star {

private String username;

private int age;

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}}

控制类改成这样:

public class MyController{

@RequestMapping("/hello")

public ModelAndView hello(Star star){

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("username", star.getUsername());

modelAndView.addObject("age", star.getAge());

modelAndView.setViewName("welcome");

return modelAndView;

}

}

(3) 域属性参数的接收

多创建一个类

public class Parter {

private String name;

}

 

 

star类中增加一个成员变量

public class Star {

private String username;

private int age;

//域属性,也称为对象属性

private Parter parter;

}

JSP提交内容:

<form action="springmvc/hello" method="POST">

用户名:<input type="text" name="username"></br>

年龄:<input type="text" name="age"></br>

伴侣名称:<input type="text" name="parter.name"></br>

<input type="submit" value="提交">

</form>

Controller类内容:

public class MyController{

@RequestMapping("/hello")

public ModelAndView hello(Star star){

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("username", star.getUsername());

modelAndView.addObject("age", star.getAge());

modelAndView.addObject("partnerName", star.getParter().getName());

modelAndView.setViewName("welcome");

return modelAndView;

}

}

welcome.jsp打印

欢迎页面!${username}--${age}--${partnerName}

(4) 数组或集合参数的接收

JSP提交内容:

<form action="springmvc/hello" method="POST">

<input type="checkbox" name="interest" value="a1">a1</br>

<input type="checkbox" name="interest" value="a2">a2</br>

<input type="checkbox" name="interest" value="a3">a3</br>

<input type="submit" value="提交">

</form>

Controller类内容:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

//数组接收参数

/*

@RequestMapping("/hello")

public void  hello(String[] interest){

for (String string : interest) {

System.out.println(string);

}

}

*/

//集合接收参数

@RequestMapping("/hello")

//使用@RequestParam校正参数

public void  hello1(@RequestParam List<String> interest){

for (String string : interest) {

System.out.println(string);

}

}

}

(5) restfull风格, 传参

涉及注解 @PathVariable

Controller类内容:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

//restful风格传参

@RequestMapping("/{name}/{age}/hello")

public void  hello1(@PathVariable String name,@PathVariable int age){

System.out.println(name+age);

}

}

浏览器地址栏输入:

http://项目地址/springmvc/zhangsan/23/hello

(6) 接收json字符串

涉及注解@RequestBody,注册mvc注解驱动,导入jackson包

index.asp内容

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.7.2.min.js"></script>

<script type="text/javascript">

$(function(){

$("#myButton").click(function(){

var data1={username:"zhangsan",age:23};

$.ajax({

url:"${pageContext.request.contextPath}/springmvc/hello",

type: "POST",

contentType:"application/json",

data:JSON.stringify(data1),

})

})

})

</script>

<title>Insert title here</title>

</head>

<body>

    <button id="myButton">点击我呀!</button>

</body>

</html>

Controller类:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

//接收json字符串并封装成对象

@RequestMapping("/hello")

public void  hello1(@RequestBody Star star){

System.out.println(star);

}

}

springmvc.xml中设置对静态资源js放行

<mvc:resources location="/js/" mapping="/js/**"></mvc:resources>

6. 获取请求头中参数

(涉及注解@RequestHeader)

index.jsp:

<a href="${pageContext.request.contextPath}/springmvc/hello">点击我呀!</a>

MyController.Java:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

//接收json字符串并封装成对象

@RequestMapping("/hello")

public void  hello1(@RequestHeader String host,@RequestHeader String cookie){

System.out.println(host + " ----------"+cookie);

}

}

输出localhost:8080----------JSESSIONID=2A1F...

7. 处理器方法的返回值

(1) ModelAndView:包含承载数据的model和视图对象view。方法既要传递数据,又要跳转资源的时候适用。

(2) String:字符串,适合跳转到视图资源

index.jsp:

<form action="${pageContext.request.contextPath}/springmvc/hello" method="POST">

姓名:<input type="text" name="username"><br/>

年龄:<input type="text" name="age"><br/>

<input type="submit" value="提交"><br/>

</form>

MyController.Java:

public class MyController{

//接收json字符串并封装成对象

@RequestMapping("/hello")

public String  hello1(String username,int age,Model model,Map<String, Object> map,ModelMap modelMap){

System.out.println(username + " ----------"+age);

model.addAttribute("username", username);

map.put("age", age);

modelMap.addAttribute("gender", "female");

return "welcome"; //由于配置了视图容器会自动拼接

}

}

 

Welcom.jsp

欢迎页面!${username}--${age}--${gender}

 

第二个例子

index.jsp:

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.7.2.min.js"></script>

<script type="text/javascript">

$(function(){

$("#myButton").click(function(){

$.ajax({

url:"${pageContext.request.contextPath}/springmvc/hello",

type: "POST",

success: function(data){

alert(data);

}

})

})

})

</script>

<title>Insert title here</title>

</head>

<body>

<button id="myButton">点击我呀!</button>

</body>

</html>

MyController.Java:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

//接收json字符串并封装成对象

@RequestMapping(value="/hello",produces="text/html;charset=utf-8")

@ResponseBody

public String  hello1(){

return "china:瓷器";

}

}

(3) void:没有返回值

index.jsp:

$(function(){

$("#myButton").click(function(){

$.ajax({

url:"${pageContext.request.contextPath}/springmvc/hello",

type: "POST",

success: function(data){

var data1 = eval("("+data+")");

alert(data1.flavor);

}

})

})

})

MyController.Java:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

//接收json字符串并封装成对象

@RequestMapping(value="/hello",produces="text/html;charset=utf-8")

public void  hello1(HttpServletResponse response) throws IOException{

String json="{\"name\":\"weilong\",\"flavor\":\"hot\"}";

response.getWriter().print(json);

}

}

 

(4) Object

涉及注解@ResponseBody , 注册mvc注解驱动, 导入jackson2. 5包

index.jsp:

$(function(){

$("#myButton").click(function(){

$.ajax({

url:"${pageContext.request.contextPath}/springmvc/hello",

type: "POST",

success: function(data){

alert(data);

}

})

})

})

 

MyController.Java:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

@RequestMapping(value="/hello",produces="text/html;charset=utf-8")

@ResponseBody  //将当前方法的返回值放到响应体中,并且转换成json格式

public Object  hello1(){

return "aaa";

}

}

8. 请求转发与重定向

(1) 从定向到另一个页面

index.jsp:

<form action="springmvc/hello" method="POST">

<input type="text" name="username"></br>

<input type="text" name="age"></br>

<input type="submit" value="提交">

</form>

MyController.Java:

public class MyController{

@RequestMapping("/hello")

public ModelAndView hello(String username,int age){

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("username", username);

modelAndView.addObject("age", age);

//重定向要写物理视图名

modelAndView.setViewName("redirect:/jsp/welcome.jsp");

return modelAndView;

}

}

 

重定向是2次请求,参数也接收不到。

地址栏的参数通过param去接收

welcome.jsp:

欢迎页面!${param.username}--${param.age}

(2) 从定向到另一个方法

MyController.Java:

@Controller //该注解表将当前类交给spring容器管理

@Scope("prototype")

@RequestMapping("/springmvc")  //该注解起到限定范围的作用

public class MyController{

@RequestMapping("/hello")

public ModelAndView hello(String username,int age){

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("username", username);

modelAndView.addObject("age", age);

modelAndView.setViewName("redirect:some"); //重定向方法名,不要以斜杠开头

return modelAndView;

}

@RequestMapping("/some")

public ModelAndView some(){

ModelAndView modelAndView = new ModelAndView();

modelAndView.setViewName("welcome");

return modelAndView;

}

}

 

其他文件同上

9. 文件上传

注册mvc注解驱动、 文件上传解析器, 导入相关jar包

(1) 上传单个文件

新导入两个jar包:

com.springsource.org.apache.commons.fileupload-1.2.0

com.springsource.org.apache.commons.io-1.4.0

index.jsp:

<form action="springmvc/fileUpload" method="POST" enctype="multipart/form-data">

<input type="file" name="img"></br>

<input type="submit" value="上传">

</form>

MyController.Java:

public class MyController{

@RequestMapping("/fileUpload")

public String fileUpload(MultipartFile img){

String path="d:/";

String fileName = img.getOriginalFilename();

File file = new File(path, fileName );

try {

img.transferTo(file);

} catch (IllegalStateException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return "welcome";

}

}

springmvc.xml

<!-- 注册文件上传解析器 -->

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.

CommonsMultipartResolver">

<!-- 解决中文乱码问题 -->

<property name="defaultEncoding" value="utf-8"></property>

</bean>

(2) 上传多个文件

index.jsp:

<form action="springmvc/fileUpload" method="POST" enctype="multipart/form-data">

<input type="file" name="imgs"></br>

<input type="file" name="imgs"></br>

<input type="file" name="imgs"></br>

<input type="submit" value="上传">

</form>

MyController.Java:

public class MyController{

@RequestMapping("/fileUpload")

public String fileUpload(@RequestParam MultipartFile[] imgs,HttpSession session){

String path=session.getServletContext().getRealPath("/");

for (MultipartFile img : imgs) {

String fileName = img.getOriginalFilename();

File file = new File(path, fileName );

try {

img.transferTo(file);

} catch (IllegalStateException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

return "welcome";

}

}

10. 文件下载

index.jsp:

<a href="${pageContext.request.contextPath}/springmvc/fileDowload">点击下载</a>

MyController.Java:

public class MyController{

@RequestMapping("/fileDowload")

public ResponseEntity<byte[]> dowload() throws IOException{

//指定下载文件

File file = new File("d:/美女.png");

InputStream is = new FileInputStream(file);

//创建字节数组,并且设置数组大小为预估的文件字节数

byte[] body = new byte[is.available()];

//将输入流中字符存储到缓存数组中

is.read(body);

//获取下载显示的文件名,并解决中文乱码

String name = file.getName();

String downLoadFileName = new String(name.getBytes("UTF-8"),"ISO-8859-1");

//设置Http响应头信息,并且通知浏览器以附件的形式进行下载

HttpHeaders httpHeaders = new HttpHeaders();

httpHeaders.add("Content-Disposition", "attachment;filename="+downLoadFileName);

//设置Http响应状态信息

HttpStatus status = HttpStatus.OK;

ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(body, httpHeaders, status);

return responseEntity;

}

}

11. 拦截器

实现HandlerInterceptor接口 ; 注册拦截器<mvc: interceptors>

(1) 单个拦截器

index.jsp:

<form action="${pageContext.request.contextPath}/springmvc/hello2" method="POST">

姓名:<input type="text" name="username"><br/>

年龄:<input type="text" name="age"><br/>

<input type="submit" value="提交"><br/>

</form>

MyController.Java:

public class MyController{

@RequestMapping("/hello")

public String  hello1(String username,int age,Model model,Map<String, Object> map,ModelMap modelMap){

System.out.println(username + " ----------"+age);

model.addAttribute("username", username);

map.put("age", age);

modelMap.addAttribute("gender", "female");

return "welcome";

}

@RequestMapping("/hello2")

public String  hello2(String username,int age,Model model,Map<String, Object> map,ModelMap modelMap){

System.out.println(username + " 2222----------2222"+age);

model.addAttribute("username", username);

map.put("age", age);

modelMap.addAttribute("gender", "female");

return "welcome";

}

}

 

创建一个拦截器类,实现HandlerInterceptor接口

public class FirstInterceptor implements HandlerInterceptor {

//该方法执行时机:处理器方法执行之前执行

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

System.out.println("拦截器preHandle()执行!");

return true;

}

//该方法执行时机:处理器方法执行之后执行

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

System.out.println("拦截器postHandle()执行!");

}

//该方法执行时机:所有工作处理完成之后,响应给浏览器客户端之前执行

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

throws Exception {

System.out.println("拦截器afterCompletion()执行!");

}

}

 

Springmvc.xml:

<!-- 注册拦截器 -->

<mvc:interceptors>

<mvc:interceptor>

<!-- <mvc:mapping path="/springmvc/hello"/> -->

<mvc:mapping path="/**"/>

<!-- <mvc:exclude-mapping path="/springmvc/hello2"/> -->

<bean id="" class="com.mypack.interceptors.FirstInterceptor"></bean>

</mvc:interceptor>

</mvc:interceptors>

 

(2) 多个拦截器

写第二个拦截器

SecondInterceptor.Java

public class SecondInterceptor implements HandlerInterceptor {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

System.out.println("Second的preHandle()执行!");

return true;

}

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

System.out.println("Second的postHandle()执行!");

}

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

throws Exception {

System.out.println("Second的afterCompletion()执行!");

}

}

 

springmvc.xml定义第二个拦截器:

<mvc:interceptor>

<mvc:mapping path="/**"/>

<bean id="" class="com.mypack.interceptors.SecondInterceptor"></bean>

</mvc:interceptor>

12. Spring和SpringMVC父子容器关系

在Spring整体框架的核心概念中, 容器是核心思想, 就是用来管理Bean的整个生命周期的,而在一个项目 中, 容器不一定只 有一个, Spring中可以包括多个容器, 而且容器有上下层关系, 目 前最常见的一种场景就是在一个项目 中引 入Spring和SpringMVC这两个框架, 那么它其实就是两个容器, Spring是父容器, SpringMVC是其子容器, 并且在Spring父容器中注册的Bean对于SpringMVC容器中是可见的, 而在SpringMVC容器中注册的Bean对于Spring父容器中是不可见的, 也就是子容器可以看见父容器中的注册的Bean, 反之就不行。