SpringMVC
Mybatis: 优化了dao层 降低了java与dao层的耦合
Spring:是大管家 整合和管理mybatis与springmve(是spring中子模块)
SpringMVC:优化了servlet层 降低了java与servlet的耦合
为什么要使用 springMVC?
SpringMVC 是一种基于 Java,实现了 Web MVC 设计模式,请求驱动类型的轻量级 Web 框架,即使用了 MVC 架构模式的思想,将 Web 层进行职责解耦。基于请求驱动指的就是使用请求-响应模型 框架的目的就是帮助我们简化开发,SpringMvc也是要简化日常 Web 开发(处理业务数据的对象和显示业务数据的视图之间存在紧密耦合)
SpringMVC XML式开发
1.创建WEB项目
2.在WEB-INF下创建lib包导入jar包
3.编写web.xml 例:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--web.xml文件是程序员与tomcat服务器打交道的配置文件用来配置servlet的访问url--><servlet><servlet-name>dispatcherServlet</servlet-name><!--在tomcat启动过程中,tomcat加载web.xml文件,并读取到DispatcherServlet并new了对象--><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern><!--/表示拦截所有的请求,交给springmvc处理同时会把静态资源全部拦截--></servlet-mapping>
</web-app>
4.创建一个类 实现Controller 例:
public class MyController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {ModelAndView m=new ModelAndView();m.addObject("name","张三");m.setViewName("a.jsp");return m;}
}
5.写dispatcherServlet-servlet.xml 注意这个配置文件一定要叫这个名 放在WEB-INF下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--下面的配置的意思是:通过在浏览器中访问/my,请求到MyContrller相当于学习servlet中配置的url-partten在spring容器中new了 MyContrller对象--><bean id="/my" class="com.springmvc.controller.MyController"></bean><!--放行静态资源--><!--/images/**表示放行images下的所有文件及其子文件中的文件--><mvc:resources mapping="/images/**" location="/images/"></mvc:resources>
</beans>
6.写jsp
<%--Created by IntelliJ IDEA.User: AdministratorDate: 2024/9/26Time: 10:31To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%String path = request.getContextPath(); //获取当前工程的根目录String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; //项目url根目录
%>
<html>
<head><base href="<%=basePath%>"> <!--这个让此文件下的路径都相对于当前工程开始--><title>Title</title>
</head>
<body>
这是第一个springMVC项目
${name}
<img src="images/~~G%7DV9PS3S~S0~GN3)H$5RO_tmb.jpg">
</body>
</html>
SpringMVC注解式开发(开发中推荐使用)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--下面的配置的意思是:通过在浏览器中访问/my,请求到MyContrller相当于学习servlet中配置的url-partten在spring容器中new了 MyContrller对象--><bean id="/my" class="com.springmvc.controller.MyController"></bean><!--放行静态资源--><!--/images/**表示放行images下的所有文件及其子文件中的文件--><mvc:resources mapping="/images/**" location="/images/"></mvc:resources><mvc:resources mapping="/html/**" location="/html/"></mvc:resources><!--上面是SpringMVC xml式开发--><!--下面是开启SpringMVC注解式开发的标签--><mvc:annotation-driven></mvc:annotation-driven><!--扫描com.springmvc.controller下所有的类--><context:component-scan base-package="com.springmvc.controller"></context:component-scan>
</beans>
@Controller//@Controller是@Component的衍生注解 意义与@Component是一样的 都是把当前类交给Spring容器管理public class MyController02 {@RequestMapping("/abc")//指定访问当前方法的限定路径的名称(uri)public ModelAndView show1() {//ModelAndView这个是封装页面共享数据和指定跳转页面的类ModelAndView m = new ModelAndView();//携带数据跳转到页面m.addObject("name","李四");m.setViewName("/a.jsp");// 这个/相当于web目录 可以加也可以不加 如果该类有限定路径名 那么一定要加/return m;}@RequestMapping("/c")//指定访问当前方法的限定路径的名称(uri)public String show2() {return "/html/c.html";//html属于静态资源需要放行}@RequestMapping("/b")//指定访问当前方法的限定路径的名称(uri)public String show3(Model m) {//spring在底层执行了 Model m=new Model();//使用Model携带数据 流转到页面上m.addAttribute("city","辽宁");return "b.jsp";//html属于静态资源需要放行}
}
SpringMVC通过注解开发 使用String携带数据 和取值
@Controller
public class UserController {@RequestMapping("/login1")public String loginUser1(String uname,String pwd,String[] favor,String birthday){/*逐个接收表达提交的数据 注意 接收的名字要与表单中 name的值一致*/System.out.println("uname:"+uname);System.out.println("pwd:"+pwd);System.out.println("favor:"+ Arrays.toString(favor));System.out.println("birthday:"+birthday);//return "forward:/success.jsp";//默认情况下就是请求转发 其实省略了 return "forward:/success.jsp"; (地址不会变)return "redirect:/success.jsp";//重定向 redirect:不能省略 (地址会改变)}@RequestMapping("/login2")public String loginUser2(String uname, String pwd, String[] favor, Date birthday){//这个Date使用的是sql包中的 包含年月日 可以接收数据/*逐个接收表达提交的数据 注意 接收的名字要与表单中 name的值一致*/System.out.println("uname:"+uname);System.out.println("pwd:"+pwd);System.out.println("favor:"+ Arrays.toString(favor));System.out.println("birthday:"+birthday);return "/success.jsp";}@RequestMapping("/login3")public String loginUser3(String uname, String pwd, String[] favor,@DateTimeFormat(pattern = "yyyy-MM-dd") java.util.Date birthday){//这个Date使用的是java.util包中的 包含年月日,时分秒 报400错误//!!!!!重要 报400错误一定是springMVC Controller接收表单提交数据 不能正常接收//处理该错误 需要指定date 年月日的格式 @DateTimeFormat(pattern = "yyyy-MM-dd") 不指定时分秒HH:MM:ss/*底层自动做了该处理 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");java.util.Date date=sdf.parse("2024-09-26");*//*逐个接收表达提交的数据 注意 接收的名字要与表单中 name的值一致*/System.out.println("uname:"+uname);System.out.println("pwd:"+pwd);System.out.println("favor:"+ Arrays.toString(favor));System.out.println("birthday:"+birthday);return "/success.jsp";}//通过对象封装数据 一次性接收@RequestMapping("/login4")//get和post方式都可以通过该注解接收public String loginUser4(User user){System.out.println("user:"+user);return "/success.jsp";}//通过restful风格的方式提交数据@RequestMapping("/restful/{name}/{pwd}")public String restful(@PathVariable String name, @PathVariable int pwd){System.out.println("name:"+name);System.out.println("pwd:"+pwd);return "/success.jsp";}//使用ajax接收值@RequestMapping(value = "/login6",produces = "text/html;charset=utf-8")//get和post方式都可以通过该注解接收@ResponseBody//响应体 表示相应的是值 不是页面了 produces = "text/html;charset=utf-8"设置响应编码public String ajax(String name,int age){System.out.println("name:"+name);System.out.println("age:"+age);return "后台接收到:"+name+"--"+age;}//使用void java内置属性传递值@RequestMapping("/login7")//get和post方式都可以通过该注解接收public void loginUser7(HttpServletRequest req, HttpServletResponse resp, HttpSession session) throws IOException {req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");String uname = req.getParameter("uname");session.setAttribute("uname", uname);resp.sendRedirect("/springMVC_01_Demo_war_exploded/success.jsp");}/*跳转到外部页面跳到百度(属于跨域访问)* */@RequestMapping("/baidu")public ModelAndView toBaidu(){RedirectView redirectView = new RedirectView("https://www.baidu.com");ModelAndView mv = new ModelAndView(redirectView);return mv;}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head><title>$Title$</title><script src="js/jquery-3.5.1.js"></script><script>$(function () {$("#but").click(function () {$.get("login6",{"name":"赵云","age":"20"},function (data) {eval("var json="+data);alert(json.name+"-"+json.age);})})})</script>
</head>
<body>
<H3>用户提交数据</H3>
<form action="login3">用户名:<input type="text" name="uname"/><br/>密码:<input type="password" name="pwd"/><br/>爱好:<br/>看书<input type="checkbox" value="1" name="favor"/>画画<input type="checkbox" value="2" name="favor"/>写字<input type="checkbox" value="3" name="favor"/><br/>生日:<input type="text" name="birthday"/><input type="submit" value="提交"/>
</form>
<a href="login5/zhangsan/123">超链接restful风格携带数据请求</a>
<button type="submit" id="but" >ajax请求</button>
</body>
</html>
视图解析
SpringMVC中的视图解析器的主要作用就是将逻辑视图转换成用户可以看到的物理视图
放在WEB-INF下面的页面都需要通过controller间接访问才可以访问到 提高了数据的安全性
手动创建视图解析器
/*放在WEB-INF下面的页面都需要通过controller间接访问才可以访问到 提高了数据的安全性*/
@Controller
public class PageController {//该方法称为:视图解析(手写版的固定视图解析器)@RequestMapping("/a")public String showPage() {return "WEB-INF/jsp/abc.jsp";}//手写版的视图解析@RequestMapping("/{uri}")// /{uri}-->restful风格的数据提交方式public String showPage(@PathVariable String uri) {String s="WEB-INF/jsp/"+uri+".jsp";System.out.println(s);return s;}
}
通过xml配置视图解析器
在dispatcherServlet-servlet.xml中
<!--配置视图解析器jsp的--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--前缀--><property name="prefix" value="WEB-INF/jsp/"></property><!--后缀--><property name="suffix" value=".jsp"></property></bean>
创建与配置配套的方法
/** 当前的方法是配套视图解析器配置使用的 不能缺!!!* */@RequestMapping("/{page}")public String page(@PathVariable String page) {System.out.println("page"+page);return page;}
配置双视图解析器jsp与html
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--下面的配置的意思是:通过在浏览器中访问/my,请求到MyContrller相当于学习servlet中配置的url-partten在spring容器中new了 MyContrller对象--><bean id="/my" class="com.springmvc.controller.MyController"></bean><!--放行静态资源--><!--/images/**表示放行images下的所有文件及其子文件中的文件--><mvc:resources mapping="/images/**" location="/images/"></mvc:resources><mvc:resources mapping="/js/**" location="/js/"></mvc:resources><!--上面是SpringMVC xml式开发--><!--下面是开启SpringMVC注解式开发的标签--><mvc:annotation-driven></mvc:annotation-driven><!--扫描com.springmvc.controller下所有的类--><context:component-scan base-package="com.springmvc.controller"></context:component-scan><!--配置视图解析器jsp的--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--前缀--><property name="prefix" value="WEB-INF/jsp/"></property><!--后缀--><property name="suffix" value=".jsp"></property><!--双视图解析器需要指定优先级--><property name="order" value="1"></property><!--value="1" 这里填写大于等于0的数 数字越小优先级越高--></bean><!--配置视图解析器html的--><bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><!--配置前缀--><property name="templateLoaderPath" value="/WEB-INF/html/"></property><!--设置编码--><property name="defaultEncoding"><value>utf-8</value></property></bean><bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"><!--设置编码--><property name="contentType" value="text/html;charset=utf-8"></property><!--配置后缀--><property name="suffix" value=".html"></property><!--指定优先级:value=(数字>=0)越小优先级越高--><property name="order" value="0"></property></bean>
</beans>
案例:文件的上传与下载
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--web.xml文件是程序员与tomcat服务器打交道的配置文件用来配置servlet的访问url--><servlet><servlet-name>dispatcherServlet</servlet-name><!--在tomcat启动过程中,tomcat加载web.xml文件,并读取到DispatcherServlet并new了对象--><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern><!--/表示拦截所有的请求,交给springmvc处理同时会把静态资源全部拦截--></servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--下面的配置的意思是:通过在浏览器中访问/my,请求到MyContrller相当于学习servlet中配置的url-partten在spring容器中new了 MyContrller对象--><!-- <bean id="/my" class="com.springmvc.controller.MyController"></bean>--><!--放行静态资源--><!--/images/**表示放行images下的所有文件及其子文件中的文件--><!--<mvc:resources mapping="/images/**" location="/images/"></mvc:resources><mvc:resources mapping="/js/**" location="/js/"></mvc:resources>--><!--上面是SpringMVC xml式开发--><!--下面是开启SpringMVC注解式开发的标签--><mvc:annotation-driven></mvc:annotation-driven><!--扫描com.springmvc.controller下所有的类--><context:component-scan base-package="com.springmvc.controller"></context:component-scan><!--配置视图解析器jsp的--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--前缀--><property name="prefix" value="WEB-INF/jsp/"></property><!--后缀--><property name="suffix" value=".jsp"></property><!--双视图解析器需要指定优先级--><property name="order" value="1"></property><!--value="1" 这里填写大于等于0的数 数字越小优先级越高--></bean><!--配置视图解析器html的--><bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><!--配置前缀--><property name="templateLoaderPath" value="/WEB-INF/html/"></property><!--设置编码--><property name="defaultEncoding"><value>utf-8</value></property></bean><bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"><!--设置编码--><property name="contentType" value="text/html;charset=utf-8"></property><!--配置后缀--><property name="suffix" value=".html"></property><!--指定优先级:value=(数字>=0)越小优先级越高--><property name="order" value="0"></property></bean><!--上传文件的配置--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!--如果上传的文件是中文的 指定编码 避免乱码--><property name="defaultEncoding" value="utf-8"></property></bean>
</beans>
@Controller
public class PageController {@RequestMapping("/{page}")public String page(@PathVariable String page) {System.out.println("page:"+page);return page;}
}
/*文件的上传与下载
* 上传
*/
@Controller
public class FileController {@RequestMapping(value = "/fileupload",produces = "text/html;charset-utf-8")@ResponseBodypublic String fileUpload(MultipartFile files) throws IOException {//这个files名字与表单中的name值一致//获取上传的文件的名字String originalFilename = files.getOriginalFilename();System.out.println(originalFilename);/** 开发中上传的文件存储在磁盘(硬盘中的某个目录下),然后把存储路径放在数据库中* */File filePath = new File("e:/datas");if (!filePath.exists()) {//如果目录不存在就创建一个filePath.mkdir();}//上传文件//为了避免文件同名覆盖 可以在originalFilename名字+毫秒值System.currentTimeMillis()File file = new File(filePath, System.currentTimeMillis()+originalFilename);files.transferTo(file);return "ok";}/*文件的上传与下载* 下载*/@RequestMapping("/filedown")@ResponseBodypublic ResponseEntity<byte[]> downLoad() throws IOException {//文件路径String path="E:\\其他/5.png";//封装pathFile file= new File(path);//从硬盘中读取文件FileInputStream in = new FileInputStream(file);//实际开发中 "E:\\datas/win2020-2024(一键激活)pro.zip"该路径在数据库中取//创建一个数组 装要下载的数据byte[] b = new byte[in.available()];//将数据存放到数组中in.read(b);//设置以附件的方式下载(小弹窗) 给响应到浏览器的对象设置响应头HttpHeaders headers = new HttpHeaders();//获取文件名称String fileName = file.getName();headers.add("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName,"utf-8"));//状态码HttpStatus status = HttpStatus.OK;//HttpStatus.OK 表示状态码为200//将数据封装到ResponseEntityResponseEntity entity = new ResponseEntity(b,headers,status);//b 存放数据的数组 headers是MultiValueMap的子类 status状态码return entity;}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%String path = request.getContextPath(); //获取当前工程的根目录String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; //项目url根目录
%>
<html>
<head><base href="<%=basePath%>"> <!--这个让此文件下的路径都相对于当前工程开始--><title>Title</title>
</head>
<body>
<form action="fileupload" method="post" enctype="multipart/form-data"><%--enctype="multipart/form-data" 提交的数据是多媒体数据(二进制的)--%><input type="file" name="files"><input type="submit" value="上传">
</form>
<h1>下载测试</h1>
<a href="filedown">下载文件</a>
</body>
</html>
Spring与SpringMVC父子容器关系
在 Spring 整体框架的核心概念中,容器是核心思想,就是用来管理 Bean 的整个生命周期的,而在一个项目中,容器不一定只有一个,Spring,中可以包括多个容器,而且容器有上下层关系,目前最常见的一种场景就是在一个项目中引入 spring和 springMvc这两个框架,那么它其实就是两个容器,Spring是父容器,SpringMvc 是其子容器,并且在 Spring父容器中注册的 Bean 对于SpringMVc容器中是可见的,而在 SpringMvc容器中注册的 Bean 对于spring父容器中是不可见的,也就是子容器可以看见父容器中的注册的 Bean,反之就不行。