(11).Spring集成SpringMVC
Spring集成SpringMVC
- 步骤一:copy jar包:org.springframework.web-3.1.0.RELEASE.jar 与 org.springframework.web.servlet-3.1.0.RELEASE.jar
- 步骤二:配置web.xml允许spring在web环境下使用(这个操作虽然肯能与集成无关,但必须要有) request -> Controller(IOC) -> 业务层 -> dao层 response <- 表示层:jsp 控制层:Controller 业务层:Service 数据层:Mappper 使用什么技术可以使spring的web工厂可以随tomcat一起启动和关闭呢?jsp技术 SpringMVC:Jsp(V)+Servlet(C)+Service(M) jsp三大组件:servlet,过滤器filter,监听器Listener(1.监听ServletContext 2.监听Session 3.监听请求) 监听器:实现ServletContextListener的接口,实现里面的方法,在web.xml中配置。tomcat在启动的时候会提醒MVC. 在SpringMVC中servlet与监听器都需要配置才可以使用 在web.xml配置文件中配置监听器:
<!--加载Spring主配置文件--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:main.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<!--注释:以监听器的形式加载Spring主配置文件--> - 配置SpringMVC: 首先了解知名的mvc框架:struts/struts2.springMVC. .netMVC(webform嫡出,mvc庶出). 前端控制器(前端拦截器): 在web.xml配置servlet:
<!--SpringMVC,WEB-INF/mvc-servlet.xml,web工厂继承主工厂--> <servlet> <servlet-name>mvc</servlet-name><!--这里的mvc会在WEB-INF创建一个为mvc-servlet.xml的配置文件--> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
此时web工厂与主工厂之间会有冲突?此时跟踪源码可以得出:这个web是main.xml的子工厂。这就是spring中两个工厂之间的关系。 然后在WEB-INF下创建一个mvc-servlet.xml的spring类型的xml文件。 mvc-servlet.xml:1.导入两个命名空间:context,mvc。
接下来以一个控制器为例来了解springMVC如何使用:(此时,与上次mybatis相比,只留下jsp,别的都不要了,关闭过滤器)
- 在web目录下创建controller.NewsController.(表示当访问localhost8888/hello时会跳转到ok.jsp)
package com.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller //声明自己是控制器 public class NewsController { @RequestMapping("/hello") //此时表示拦截的是hello的请求或界面(www.localhost.8888/hello) public String hello(){ return "ok"; } }
上面写了之后,需要让spring知道,需要让spring扫描一下,在mvc-servlet.xml文件中添加扫描,使spring承认控制器。
<context:component-scan base-package="com.web.controller"/>
此时遇见一个问题:就是在web.xml中设置mvc中,url-parten我们设置的是/*,那么代表所有都会拦截,此时我们可以仅设为/。可以试一下 到此:我们已经了解了一个小的例子,那么我们可以把servlet中的一个方法设置一个RequestMapping来解决。
Controller使用:
- 参数传递。 我们想传递两个参数:
String nickname,String pwd 在方法中设置参数:
@Controller public class NewsController { @RequestMapping("/hello") public String hello(String nickname,String pwd){ return "ok.jsp"; }
那么此时我们请求界面hello,可以设为http://localhost:8888/hello?nickname=admin&pwd=123 那么hello方法中会接收到这两个参数。如果参数过多,则使用对象类型参数。
- 对象类型参数
@Controller public class NewsController { @RequestMapping("/hello") public String hello(Users user){ return "ok.jsp"; }
此时我们的调试代码为:http://localhost:8888/hello?nickname=admin&pwd=123&type=2 那么这三个值会自动传入一个user对象,里面会有这三个属性。
向页面发送数据:
- 我们想向页面返回值,我们可以声明一个集合。但是要求Map必须是方法的一个参数,可以是Map或Model类型。
@Controller public class NewsController { @RequestMapping("/hello") public String hello(Map model, Users user){ model.put("user",user);//相当于request.setAttribute("user",user); return "ok.jsp"; }
在页面取值:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>${user.nickname},${user.pwd},${user.type}</h1> </body> </html>
此时我们的调试代码为:http://localhost:8888/hello?nickname=admin&pwd=123&type=2 最终调试结果是ok.jsp页面显示,admin,123,2.
- 控制类的return可以直接返回页面会自动跳转。eg:return "ok.jsp"; 重定向:eg: return "redirect:ok.jsp" 但是重定向无法访问我们要返回的Map中的参数。 关于重定向无法访问Map参数的解决办法:1.不用重定向。2.使用HttpSession session
@Controller public class NewsController { @RequestMapping("/hello") public String hello(Map model, Users user , HttpSession sessin){ //model.put("user",user);//request.setAttribute("user",user); sessin.setAttribute("user",user); return "redirect:ok.jsp"; }
当使用会话sessino实现的时候,就jsp页面不用改,因为${}表达式,本身就可以从session中获取。结果和Map之前是一样的。
spring输出各种数据信息:
- 返回字符串。 http://localhost:8888/show
@RequestMapping("/show") @ResponseBody public String show(){ return new Date().toLocaleString();//把时间转化为字符串 }
会返回当前的这个,是时间。
2.可以返回一段html:
@RequestMapping("/showHtml") @ResponseBody public String showHtml(){ return "<fond style='color:red'>"+new Date().toLocaleString()+"<fond>"; }
此时就是把字体变为了红色
http://localhost:8888/showHtml 3.返回Json :Json格式:var person={name:"张三",age:20} var nums=[1,2,3,4]
@RequestMapping("/showJson") @ResponseBody public String showJson(){ return "{\"time\":\""+new Date().toLocaleString()+"\"}"; }
此时在web界面接受为下面的方法二:其中eval();是动态执行语言。其中ajax.open中的url换成/showJson
- 使用script的ajax创建一个服务器数字时钟。创建一个timer.jsp。html代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <title>Title</title> <script type="text/javascript"> window.onload=function(){ //注册事件处理函,可以解决访问下面为执行为读到的参数,这里是time与下面span中的time function freshTimeFromServer(){ var time = document.getElementById("time"); // 通过javascript发送请求,获取服务器时间 var ajax = new XMLHttpRequest(); // ajax对象 ajax.open("get","/show",true); // 设置请求的参数,(请求的方式,对应的控制器的方法的url,true代表是异步) ajax.onreadystatechange = function(xhr,e){ // 注册事件处理函数 // 服务器响应后进行处理,http响应码:2xx(200),3xx,4xx,5xx ,表示接收到回旋镖 // 收到正常数据后 ajax.readyState == 4 表示收到的数据是正常的 if(ajax.status == 200 && ajax.readyState == 4){//ajax.status表示http的响应码,
//方法一:下两行 var info = ajax.responseText; // 服务器返回的数据 time.innerHTML = info; // 量时间显示到span标签中 // json 方法二:下三行 是处理Json格式 /*var obj = {}; // "obj = {\"time\":\"2020-05-20\"}"; eval("obj = "+ajax.responseText);// {time:"2020-05-20"} time.innerHTML = obj.time;*/ // 1秒钟后再次执行 setTimeout(freshTimeFromServer,1000); } }; ajax.send();//表示扔出回旋镖 } freshTimeFromServer(); } </script> </head> <body> <h1>时钟:<span id="time"></span></h1> </body> </html>其中ajax.open("get","/show",true);里的/show是和上面是一样的,也可以换成/showHtml。适用于方法一。
当请求出问题:有两个控制器,当两个控制器映射到同一个目录,即两个控制器中有相同的RequstMapping命名,如果有两个/show,则会报错。
解决办法:在控制器类前设置上级别,如下:
package com.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @RequestMapping("/users") @Controller public class UsersController { @ResponseBody @RequestMapping("/show") public String show(){ return "ok"; } }
那么此时的访问路径则会由之前的localhost:8888/show转变为localhost:8888/users/show.