SpringMVC_基础
1.SpringMVC是什么?
SpringMVC 是 Spring 基础上开发的控制器框架 ,在现有MVC架构中充当控制器,也是一个典型的MVC框架。
SpringMVC可以替换项目中现有的struts2技术。
2.SpringMVC第一个环境搭建
1)引入依赖
<dependencies>
<!--spring框架的相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--springMVC的相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--面向切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<!--servlet 及 jsp-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
2)配置web.xml
DispatcherServlet 使用servlet标签 url-pattern /
<!--springmvc核心servlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas
<init-param>
<!--固定写死用来加载springmvc配置文件的位置-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--拦截所有请求交给springmvc处理-->
<url-pattern>/</url-pattern>
</servlet-mapping>
3)引入springmvc.xml 配置文件
位置:随便 名字:随便 推荐:springmvc.xml并放置在resource根目录下
0.开启注解扫描
1.处理器映射器
2.处理器适配器
3.视图解析器
<!--开启注解扫描,并指定只扫描Controller-->
<context:component-scan base-package="com.itheima.springmvc.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--注册处理器映射器 及 处理器适配器-->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
<!--spring3.x 以后不建议上面的写法,可用<mvc:annotation-driven/>替代-->
<!--<mvc:annotation-driven/>中还包含对参数类型的转换,跳转,相应处理等-->
<mvc:annotation-driven/>
<!--注册 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
4)开发xxxController控制器,加入相关注解
@Controller
@RequestMapping("user")
public class UserController {
/**
* @RequestMapping:可以修饰在 类上 和 方法上
* 1. 用在方法上,可以给当前方法加入指定的请求路径
* 2. 用在类上,可以给类中所有的方法加入统一的请求路径,
* 在方法访问之前需要加入类上的@RequestMapping的路径
* @return
*/
@RequestMapping("hello")
public String hello(){
//1.收集数据
//2.调用业务方法
System.out.println("hello spring mvc");
//3.处理相应
return "index";
}
}
3.SpringMVC中的跳转方式
1)原始Servlet技术中跳转方式
- forward跳转:请求转发
- 特点:服务器内部跳转,跳转之后地址栏不变。一次跳转,跳转时可以使用request作用域传递数据。
- redirect跳转:请求重定向
- 特点:客户端跳转,跳转之后地址栏改变。多次跳转,跳转过程不能使用request作用域传递数据。
2)SpringMVC中跳转方式
- Controller ----> JSP页面跳转
- forward跳转:默认使用的就是forward跳转到也页面
- 具体语法:return “页面逻辑名”;
- redirect跳转:使用SpringMVC提供的关键字:redirect,
- 具体语法:return “redirect:视图全名”;如:return “redirect:/index.jsp”;
- 注意:使用redirect跳转不会经过视图解析器
- forward跳转:默认使用的就是forward跳转到也页面
- Controller ----> Controller 之间跳转(相同|不同控制器)
- forward|redirect 跳转:使用springmvc提供的关键字forward|redirect :
- return “forward|redirect: /跳转controller类上@RequestMapping的路径/跳转类中指定方法上@RequestMapping的路径”
- forward|redirect 跳转:使用springmvc提供的关键字forward|redirect :
4.SpringMVC中的参数接收
- 语法:使用控制器中方法的形参列表接收客户端的请求参数。
- 要求:要求传递参数的key要与对应方法的形参变量名一致才能完成赋值操作。
4.1 零散类型的参数接收
@RequestMapping("param")
@Controller
public class ParamController {
/**
* 用于测试零散类型参数接收
* 路径:http://localhost:8080/springMVC_war/param/test?username=老王&age=23
* @return
*/
@RequestMapping("test")
public String test(String username,Integer age){
System.out.println("username = " + username);
System.out.println("age = " + age);
return "index";
}
}
4.2 对象类型的参数接收
-
创建对象实体类
public class User { private String username; private Integer age; @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + '}'; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
-
对象作为控制器方法的形参,SpringMVC会自动完成请求参数到对象的封装:
@RequestMapping("param") @Controller public class ParamController { /** * 用于测试对象类型参数接收 * 路径:http://localhost:8080/springMVC_war/param/test?username=老王&age=23 * @return */ @RequestMapping("test") public String test(User user){ System.out.println("user = " + user); return "index"; } }
注意:springmvc封装对象时直接根据传递参数key与对象中属性名一致自动封装对象。
4.3 数组或集合类型的参数接收
-
数组类型参数的接收:
@RequestMapping("param") @Controller public class ParamController { /** * 用于测试对象类型参数接收 * 路径:http://localhost:8080/springMVC_war/param/test?names=老王&names=james * @return */ @RequestMapping("test") public String test(String[] names){ System.out.println("names = " + Arrays.toString(names)); return "index"; } }
-
集合类型参数的接收:
-
注意:
SpringMVC不能直接通过形参列表方式收集集合类型参数. 如果要接收集合类型的参数必须将集合放入对象中接收才可以,推荐放入VO对象中接收集合类型 VO --> Value Object 值对象
-
创建VO类,将集合作为其成员变量:
public class CollectionVO { private List<String> names; public List<String> getNames() { return names; } public void setNames(List<String> names) { this.names = names; } }
-
将VO对象作为控制器方法的形参,SpringMVC会自动将集合参数封装到VO对象的成员变量中:
@RequestMapping("param") @Controller public class ParamController { /** * 用于测试集合类型参数接收 * 路径:http://localhost:8080/springMVC_war/param/test?names=老王&names=james * @return */ @RequestMapping("test") public String test(CollectionVO collectionVO){ collectionVO.getNames().forEach(str-> System.out.println("str = " + str)); return "index"; } }
-
5.SpringMVC两种请求方式出现中文乱码
5.1 GET方式的请求出现乱码
tomcat8.x版本之前:默认使用server.xml 中URIEncoding = "iso-8859-1"编码不是utf-8,所以会出现中文乱码
tomcat8.x版本之后:默认使用server.xml 中URIEncoding = “utf-8”,解决了中文乱码问题
5.2 POST方式的请求出现乱码
-
解决方案:
-
自定义filter,设置request和response对象编码为utf-8:
/** * @Author:Unique.L * @Date: 2020/11/4 12:15 * @Description: 自定义编码的Filter类 */ public class MyCharacterEncodingFilter implements Filter { private String encoding; /** * 在Filter类的初始化方法中获取配置的信息,赋值给成员变量 * @param filterConfig * @throws ServletException */ @Override public void init(FilterConfig filterConfig) throws ServletException { this.encoding = filterConfig.getInitParameter("encoding"); } /** * 通过filter过滤器设置request和response对象编码为指定的编码 * @param servletRequest * @param servletResponse * @param filterChain * @throws IOException * @throws ServletException */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding(encoding); servletResponse.setCharacterEncoding(encoding); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
<!--使用自定义的编码filter,解决post请求的中文乱码--> <filter> <filter-name>charset</filter-name> <filter-class>com.itheima.springmvc.filter.MyCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>charset</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
使用springmvc提供好的编码filter:CharacterEncodingFilter
<!--使用springmvc提供好的编码filter,解决post请求的中文乱码问题--> <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> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
6.SpringMVC中的数据传递机制
6.1 数据传递机制
数据怎么存储? | 数据在页面如何获取? | 在页面中获取的数据该如何展示? | |
---|---|---|---|
Servlet | request, session, application | EL表达式 | EL+JSTL标签 展示 |
Struts2 | request, session, application | EL表达式 | EL+JSTL标签 展示 |
SpringMVC | request, session, application | EL表达式 | EL+JSTL标签 展示 |
6.2 存数据具体使用哪种作用域?
具体使用哪种作用域,取决于跳转方式:
- forward(一次请求):使用request作用域(Model(SpringMVC提供));
- redirect(多次请求):使用session作用域、application作用域【不推荐】、?地址栏传递数据(少量数据)
6.3 SpringMVC控制器方法中获取request对象和response对象
/**
* 注解将request、response对象作为控制器方法参数声明即可获取
* @param request
* @param response
* @return
*/
@RequestMapping("findAll")
public String findAll(HttpServletRequest request, HttpServletResponse response){
request.getSession();
request.getSession().getServletContext();
return "index";
}
6.4 SpringMVC两种请求方式的参数传递
@Controller
@RequestMapping("attr")
public class AttrController {
/**
* 使用forward跳转页面传递数据
* @return
*/
@RequestMapping("test")
public String test(Model model, HttpServletRequest request){
//1.零散类型的数据
String name = "小城";
request.setAttribute("name",name);
//2.对象类型的数据
User user = new User("James",36);
model.addAttribute("user",user);
//3.集合类型的数据
List<String> list = Arrays.asList("asd", "123");
model.addAttribute("list",list);
return "attr";
}
/**
* 使用redirect跳转页面传递数据
* @return
*/
@RequestMapping("test1")
public String test1(HttpServletRequest request) throws UnsupportedEncodingException {
//1.使用session域传递数据
HttpSession session = request.getSession();
User user = new User("James",36);
session.setAttribute("user",user);
//2.使用?地址值传递少量数据
return "redirect:/attr.jsp?name="+ URLEncoder.encode("小王","UTF-8");
}
}
7.Spring+SpringMVC+MyBatis整合
-
引入依赖
spring、springmvc、mybatis、mybatis-spring、mysql、druid、log4j、servlet-api、jstl、fastjson等
-
SM整合
- 建表
- 实体类
- DAO接口
- Mapper文件
- Service接口
- Service实现类,加上@Service、@Transactional,注入DAO对象
- 引入spring的applicationContext.xml编写Spring整合MyBatis的配置:
- 开启注解扫描:<context:component-scan base-package=“com.itheima”/>
- 创建数据源对象datasource,注入四大属性
- 创建SqlSessionFactoryBean,注入datasource,mapperLocations,typeAliasesPackage
- 创建MapperScannerConfigurer,注入basePackage、sqlSessionFactoryBeanName
- 创建DataSourceTransactionManager,注入datasource
- 开启注解式事务控制驱动:<tx:annotation-driven transaction-manager=“transactionManager”/>
- 测试Service方法调用
-
SS整合
-
配置web.xml
-
启动工厂监听器 ContextLoaderListener
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
-
配置工厂配置文件 applicationContext.xml:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
-
配置springmvc的核心前端控制器 DispatcherServlet:
-
配置springmvc接收post请求的中文乱码问题,CharacterEncodingFilter:
-
-
引入springmvc.xml配置
- 开始注解扫描
- 配置处理器映射器 及 处理器适配器
- 配置视图解析器
-
开发Controller,加上@Controller、@RequestMapping,注入XxxService。
-
服务器部署进行访问测试。
-
8.SpringMVC中的静态资源拦截问题
8.1 出现静态资源拦截问题的原因
由于在web.xml中配置springmvc的核心servlet DispatcherServlet 时url-pattern 配置为“/”,
因此会导致项目中所有/开头的请求,均被作为控制器请求处理,这样会导致项目中的静态资源(css\js\img)被拦截
8.2 解决方案
-
更改url-pattern,不使用“/”,而是使用“*.do”的形式。
- 存在的弊端:使用这种方式日后访问路径结尾必须加上指定的后缀 url.do
-
url-pattern继续使用“/”,在springmvc.xml配置文件中加入如下配置:
<mvc:default-servlet-handler/>