0、三阶段的内容:
SSM框架—SpringMVC + Spring + MyBatis + Redis + Nginx
做一个项目
SpringBoot + Vue 也要做一个项目
一、三层架构+MVC模型
三层架构:
表现层:web层,不是说页面的,而是和页面打交道的java层(Servlet,SpringMVC)
Servlet —> SpringMVC Struts2
业务层:提供服务的层面 Service层 —>Spring
持久层: 关于数据的层面 Dao层(MySQL + Redis。。。)
太多的框架—>jdbc,jdbcTemplate,Mybatis,JPA,Hibernate。。。。。
MVC模型:—SpringMVC
M: Model 数据模型 —> POJO
V:View 视图 jsp,html
C: Controller 控制层(Servlet)
二、SpringMVC的概念
SpringMVC是由Spring基金组织开发的,符合MVC模型的这样一种表现层的框架。它是基于Servlet实现的。工作职责就是替代servlet,完成页面上的数据到java代码,java代码的数据传递给页面,还可以进行界面的跳转。
它和Struts2一样都是一个web层框架,Struts2是一个基于filter实现的web框架。
三、SpringMVC入门案例
1、创建一个maven的web项目,导入jar包
新建完项目之后,导入jar包
如果遇到导入包之后没啥反应的,可以如下操作
<!--一定要编写打包方式,否则,项目启动之后无法访问-->
<packaging>war</packaging>
<!--定义各个jar包的版本号,后面统一通过${} 的方式引用该版本号-->
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
2、编写代码—Controller
@Controller //编写一个注解,用于表示该类是一个Controller类
public class HelloController {
@RequestMapping("/hello")
public String sayHello(){
System.out.println("这是我的第一个Controller");
return "success.jsp";//此处需要写跳转页面的路径
}
}
3、编写一个页面
在webapp文件夹下,编写了一个success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
跳转到该页面,表示你的代码已经成功了!
</body>
</html>
3、编写springmvc.xml 这个是必须写的,将来所有的springmvc的配置都编写在该xml中。在resources文件夹下创建
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描你的所有关于@Controller的注解的类-->
<context:component-scan base-package="com.qfedu.controller"/>
<!--开启注解-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
4、配置前端控制器(总开关,大脑,BOSS)—在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">
<!--配置前端控制器DispatcherServlet-->
<servlet>
<servlet-name>dispatcherServlet</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>
<!--tomcat一启动就让其加载该servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
遇到的问题:
当你编写的项目,编译完之后出现了 out target两个编译完之后的文件夹,要警惕
出现了部署上的问题
解决方案:
1、使用tomcat插件(不建议大家用)
2、检查部署上有啥问题
http://localhost/虚拟路径名/hello
四、原理分析
1)加载顺序的原理:
1、tomcat一启动,加载web.xml,dispatcherServlet就会被加载,因为<load-on-startup>1</load-on-startup>
加载的时候创建dispathcherServlet,创建的时候加载了
2、该配置文件一加载,就去扫描com.qfedu.controller下的所有带有@Controller的注解的类
3、带有@Controller的注解都被spring容器,给加载到了jvm内存中,并且帮我们创建好了Controller的实例化对象,等着以后使用即可。
2)执行原理
面试重点:springmvc运行原理图 (戏称 一个中心DispatcherServlet三个基本点【处理器映射器,处理器适配器,视图解析器】)
1、浏览器发送请求 /hello 给前端控制器DispatcherServlet ,这个是一个大脑,控制所有其他组件的运行
2、前端控制器去问处理器映射器(编写了一堆某个url对应某个类中的哪个方法),处理器映射器告诉前端控制器,哪个类中的哪个方法可以处理
3、前端控制器去找处理器适配器,告诉它执行哪个类中的哪个方法,处理器适配器接到命令之后,就去执行处理器(Handler),其实就是一个方法,也就是说一个方法就是一个处理器。处理器执行完方法之后,将一个ModelAndView对象给处理器适配器,处理器适配器上交处理结果—ModelAndView(数据+页面)
4、前端控制器拿着ModelAndView 对象传递给视图解析器,让其解析,解析的结果传递给前端控制器
5、前端控制器拿到渲染之后的页面,传递给浏览器。
关注点:前端控制器,处理器映射器,处理器适配器,视图解析器,都不需要我们来管,自动运行的,我们开发人员只需要关注处理器如何编写,页面如何编写即可。
拓展:
关于web-inf下的资源,是无法通过浏览器直接访问到的。资源存放在这个文件夹下面,是非常安全的。但是我们如何访问到它呢?
我们通过视图解析器访问到该资源。
@RequestMapping("/a")
public String sayA(){
System.out.println("此处访问一个隐蔽的资源");
return "WEB-INF/page/a.jsp";
}
以上方案解决了安全性问题,也访问到了我们想要的资源,但是每次路径很重复。我们可以通过配置视图解析器的方式来解决。
<!--配置视图解析器解决访问路径过长的问题-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"/>
<property name="suffix" value=".jsp"/>
</bean>
classpath : 类路径, 编译完之后的classes文件夹
五、参数的传递(绑定)
springmvc —> 1、将页面的数据传递给controller
2、将java代码(Controller)中的数据,传递给页面
3、跳转页面
支持的数据类型:
1、基本数据类型和字符串类型
[http://localhost/SpringMVC_01/edit?id=10&name=zhangsan](http://localhost/SpringMVC_01/edit?id=10&name=zhangsan) 模拟的是get请求,post请求也是一样的,只需要表单中的参数名字和方法中的参数名字一样就可以了<br /> 我们只需要保证请求的参数名字和方法的变量的名字一样,就可以直接赋值
@RequestMapping("/edit")
public String getParams01(int id,String name){
System.out.println(id);
System.out.println(name);
return "a";
}
2、实体类型
<form action="${pageContext.request.contextPath}/save" method="post">
姓名: <input name="name" type="text"/><br/>
手机号: <input name="phone" type="text"/><br/>
身份证号: <input name="cardNum" type="text"/><br/>
<input type="submit" value="提交"/>
</form>
public class User {
private String name;
private String phone;
private String cardNum;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", phone='" + phone + '\'' +
", cardNum='" + cardNum + '\'' +
'}';
}
}
@RequestMapping("/save")
public String save(User user){
System.out.println(user);
return "a";
}
一定要注意:页面中的表单中的name值,一定要和实体中的属性名称保持一致,否则,数据无法传递。
实体中的属性指的是什么?getName-> Name —>name 这个才是属性,而不是类中的变量名。
3、集合类型(list\map类型)— 不常用
解决中文乱码问题—提交数据的时候的中文乱码 web.xml
<!--解决页面上的数据到controller中,中文乱码问题-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
六、常用的注解
1、RequestMapping 请求映射
1)ElementType.**_METHOD_**, ElementType.**_TYPE 说明该注解可以使用在方法和类上。_**<br />**_ 2)path value 两者是一会儿事儿 都可以存放数组 _**@RequestMapping(path={**"/demo01"**,**"/demo02"**})<br /> [http://localhost/SpringMVC_01/user/demo02](http://localhost/SpringMVC_01/user/demo02) <br /> 3)method 限定某个url中的方法,必须是某一种类型,比如我指定是post请求方式,get方式就不可以 RequestMethod<br /> method = RequestMethod.**_GET_**
2、RequestParam
问题: http://localhost/xxxxx/save?id=10&name=zhangsan<br /> public String show(int id,String username){<br /> }<br /> 解决请求参数和方法中的参数名字不一致的问题。<br /> 1、 一般作用于参数前面,可以指定url中的名称和参数名称的一个对应关系 username-->name <br /> 2、可以指定某些参数是否为必须的。默认都是必须的<br /> 3、可以指定某些参数的一个默认值,当前端页面没有传递该值时,可以使用指定的默认值。<br />代码演示:
//http://localhost/SpringMVC_01/user/demo03?username=zhangsan
@RequestMapping("/demo03")
public String b(@RequestParam(value ="username",required = true,defaultValue = "老闫") String name) {
System.out.println(name);
return "a";
}
3、PathVariable 注解 — 可以通过该注解实现restful风格的请求
http://localhost:8080/xxxxx/save?id=1&name=zhangsan&age=10<br /> restful风格的请求:[http://localhost/SpringMVC_01/user/edit/1/zhangsan/10](http://localhost/SpringMVC_01/user/edit/1/zhangsan/10)<br /> restful风格的请求:结构清晰,易于理解,拓展方便,非常流行
//http://localhost:8080/xxxxx/edit/1/zhangsan/10
@RequestMapping("/edit/{id}/{name}/{age}")
public String c(@PathVariable(value="id")int sid,@PathVariable(value="name") String sName,@PathVariable(value="age") int age){
System.out.println(sid);
System.out.println(sName);
System.out.println(age);
return "a";
}
七、补充—数据类型转换器
页面上有个生日:birthday User 实体中 Date birthday<br /> 页面上的是String -- > Date<br /> 1、 需要先写一个数据类型转换器:
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
if(source == null || source.equals("")){
return null;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
2、配置转换器 一定要记得,在注解驱动里面配置一下
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.qfedu.converter.StringToDateConverter"/>
</set>
</property>
</bean>
<!--开启注解-->
<!--<mvc:annotation-driven></mvc:annotation-driven>-->
<mvc:annotation-driven conversion-service="conversionService"/>
至此,我们提交表单数据时,遇到实体中有Date类型就能正常解析了。