ContextLoaderListener监听器
应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件)方式获取的,但是每次从
容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) ,这样的弊端是配置
文件加载多次,应用上下文对象创建多次。
在Web项目中,可以使用ServletContextListener监听Web应用的启动, 我们可以在Web应用启动时,就加
载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域
中,这样就可以在任意位置从域中获得应用上下文ApplicationContex对象了。
自定义监听器实现
业务层代码
package com.ytl.web;
import com.ytl.listen.WebApplicationContextUtils;
import com.ytl.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// ApplicationContext applicationContext = (ApplicationContext) this.getServletContext().getAttribute("applicationContext");
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.save();
((ClassPathXmlApplicationContext) applicationContext).close();
}
}
工具类
package com.ytl.listen;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
public class WebApplicationContextUtils {
public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
return (ApplicationContext) servletContext.getAttribute("applicationContext");
}
}
监听器类
package com.ytl.listen;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
//读取 web.xml 中的全局参数
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(contextConfigLocation);
//将创建的配置文件对象存入web中的最大的 ServletContext 域
servletContext.setAttribute("applicationContext", applicationContext);
System.out.println("上下文对象创建完毕");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
((ClassPathXmlApplicationContext)servletContextEvent.getServletContext().getAttribute("applicationContext")).close();
System.out.println("上下文对象销毁完毕");
}
}
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 全局初始化参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<!-- 配置servlet-->
<servlet>
<servlet-name>userServlet</servlet-name>
<servlet-class>com.ytl.web.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
<!-- 配置自定义监听器-->
<listener>
<!-- <listener-class>com.ytl.listen.ContextLoaderListener</listener-class>-->
<!-- spring提供的-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Spring提供的获取应用上下文的工具
- 配置ContextLoaderListener监听器
- 使用WebApplicationContextUtils获得应用上下文
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
assert applicationContext != null;
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.save();
SpringMVC
开发步骤
客户端发起请求,服务器接收请求,执行逻辑并进行视图跳转。
- 导入SpringMVC相关坐标
- 配置SpringMVC核心控制器
DispathcerServlet
- 创建Controller类和视图页面
- 使用注解配置
Controller
类中业务方法的映射地址 - 配置SpringMVC核心文件
spring-mvc.xml
- 客户端发起请求测试
web.xml
<!-- 配置springMvc的前端控制器-->
<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*:spring-mvc.xml</param-value>
</init-param>
<!-- web服务器启动时就加载此Servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!-- 所有请求都经过该控制器-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 全局初始化参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
spring-mvc.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Controller的组件扫描-->
<!-- spring-mvc只负责扫描前端控制器-->
<context:component-scan base-package="com.ytl.controller" />
</beans>
UserController
package com.ytl.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
//将此类放在spring容器中
@Controller
public class UserController {
@RequestMapping("/login")
public String save() {
System.out.println("前端控制器启动了");
return "success.jsp";
}
}
SpringMvc的执行流程
- 用户发送请求至前端控制器
DispatcherServlet
。 DispatcherServlet
收到请求调用HandlerMapping
处理器映射器- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给
DispatcherServlet
。 DispatcherServlet
调用HandlerAdapter
处理器适配器。HandlerAdapter
经过适配调用具体的处理器(Controller
,也叫后端控制器)。Controller
执行完成返回ModelAndView
。HandlerAdapter
将controller
执行结果ModelAndView
返回给DispatcherServlet
.DispatcherServlet
将ModelAndView
传给ViewReslover
视图解析ViewReslover
解 析后返回具体View。DispatcherServlet
根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet
响应用户。
SpringMVC注解解析
名称 | 说明 |
---|---|
@RequestMapping | 用于建立请求URL和处理方法之间的对应关系 |
@ResponseBody | 告知Spring容器不进行试图跳转,直接进行数据响应 |
作用:用于建立请求URL和处理请求方法之间的对应关系位置
405- Method not Allowed
可以放的位置
- 类上,请求URL的第一级访问目录。此处不写的话,就相当于应用的根目录
- 方法上,请求URL的第二级访问目录,与类上的使用
@ReqquestMapping
标注的一级目录一起组成访问虚拟路径
//默认从当前二级目录中寻找
return "success.jsp";
//默认从根路径下寻找
return "/success.jsp";
属性:value,method,params
value
:用于指定请求的URL。它和path属性的作用是一样的- method:用于指定请求的方式,可取值有:
RequestMethod.POST
RequestMethod.GET
- params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和配置的一模一样例如:
- params = {“username”,“age!18”}
- 表示请求参数中必须有username,age,且age的值不能为18
<!-- Controller的组件扫描-->
<!-- spring-mvc只负责扫描前端控制器-->
<!-- <context:component-scan base-package="com.ytl.controller"/>-->
<context:component-scan base-package="com.ytl">
<!-- 会扫描当前包下的Controller注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!-- 不会扫描当前包下的Service注解-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
SpringMVC的数据响应
- 页面跳转
- 直接返回字符串
- 通过ModelAndView对象返回
- 回写数据
- 直接返回字符串
- 返回对象或集合
页面跳转
- 请求转发(默认的)
<!-- 配置内部资源视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置前缀,好像无法使用重定向?-->
<property name="prefix" value="/jsp/" />
<!-- 配置后缀-->
<property name="suffix" value=".jsp" />
</bean>
return "success";//相当于
return "forward:/jsp/success.jsp"
- 重定向
return "redirect:/jsp/success.jsp"
返回ModelAndView对象
@RequestMapping("/login2")
public ModelAndView login2(){
System.out.println("来到登录功能2");
/*
Model:模型,用来封装数据
View:视图,返回数据
*/
ModelAndView modelAndView = new ModelAndView();
//设置视图名称
modelAndView.setViewName("success");
//设置模型数据
modelAndView.addObject("userName", "余腾龙");
return modelAndView;
}
@RequestMapping("/login3")
public ModelAndView login3(ModelAndView modelAndView){
System.out.println("来到登录功能3");
//设置视图名称
modelAndView.setViewName("success");
//设置模型数据
modelAndView.addObject("userName", "余腾龙2");
return modelAndView;
}
@RequestMapping("/login4")
public String login4(Model model){
//将模型和数据拆开
System.out.println("来到登录功能4");
//设置模型数据
model.addAttribute("userName", "余腾龙2");
return "success";
}
注意:
maven项目web.xml版本用的是2.3版本的,如果web.xml是2.3版本的话,jsp里面有个默认的属性是:
<%@ page isELIgnored="true"%>
如果这个属性设置为true的话,默认el表达式是关闭的,所以我们可以在.jsp文件里面加入如下代码:
<%@ page isELIgnored="false"%>
如果是一两个jsp文件,我们这样改可能没什么,如果是太多jsp文件的话,这样子改就未必太麻烦了,如果我们想用一劳永逸的方法的话,最好是去修改xml的版本问题:
我们可以把web.xml的版本换成3.0的,这样子是默认支持el表达式的,我们就不需要再去修改jsp文件了。
返回字符串形式
此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转
@RequestMapping("/login")
public String login(){
System.out.println("来到登录功能");
//默认省略forward请求转发
// return "forward:/success.jsp";
return "redirect:/success";
}
回写数据
直接返回字符串
web:responsse.getWriter().print(“hello World!”)
@RequestMapping("/welcome1")
public void welcome1(HttpServletResponse response) throws IOException {
//加上形参,Spring容器就会帮忙注入
//web的回写方法
System.out.println("来到欢迎功能1");
response.getWriter().println("welcome1");
}
@ResponseBody//告知Spring 此方法是直接返回字符串
@RequestMapping("/welcome2")
public String welcome2() throws IOException {
//加上形参,Spring容器就会帮忙注入
//web.的回写方法
System.out.println("来到欢迎功能2");
return "welcome2";
}
@ResponseBody//告知Spring 此方法是直接返回字符串
@RequestMapping("/welcome3")
public String welcome3() throws IOException {
User user = new User("liSi", 30);
//JSON转换工具将对象转换为JSON格式的字符串
System.out.println("来到欢迎功能3");
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
return json;
}
返回对象或集合
@ResponseBody//告知Spring 此方法是直接返回字符串
@RequestMapping("/welcome4")
public User welcome4() {
System.out.println("来到欢迎功能4");
//期望Spring自动的将User对象转换为JSON格式的字符串
//直接返回即可,需要在spring-mvc.xml文件中配置
return new User("liSi", 30);
}
spring-mvc.xml
<!-- json转换的配置-->
<!-- 配置处理器映射器,转JSON字符串用的-->
<bean id="requestMappingHandlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
<!-- 配置处理器映射器,注解方式的mvc的注解驱动-->
<mvc:annotation-driven />
<!-- json转换的配置-->
在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。
使用<mvc:annotation- driven>自动加载RequestMappingHandlerMapping (处理映射器)和
RequestMappingHandlerAdapter (处理适配器), 可用在Spring-xml.xml配置文件中使用
<mvc:annotation- driven>替代注解处理器和适配器的配置。
同时使用<mvc:annotation-driven>默认底层就会集成jackson进行对象或集合的ison格式字符串的转换。
pom.xml
<!-- JSON-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<!-- JSON-->
SpringMVC获取请求数据
SpringMVC可以接收如下类型的数据:
- 基本类型参数
- POJO类型参数,简单JavaBean
- 数组类型参数
- 集合类型参数
获得基本类型参数
Controller中的业务方法的参数名称要与请求参数的name一致,参数值就会自动映射匹配
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping("/save1")
public void save1(String userName, int age){
//形参要与传入的参数名字保持一致
System.out.println("Controller中的save1方法执行");
System.out.println("接收到的数据:userName=="+userName+"\tage=="+age);
}
POJO类型参数,简单JavaBean
Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值就会自动映射匹配
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping("/save2")
public void save2(User user){
//形参要与传入的参数名字保持一致name,age
System.out.println("Controller中的save2方法执行");
System.out.println("接收到的数据:"+user);
}
数组类型参数
Controller中的业务方法的数组名称与请求参数的name一致,参数值就会自动映射匹配
/save3?strs=zhangsan&strs=lisi&strs=wangwu
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping("/save3")
public void save3(String[] strs){
//形参数组要与传入的数组参数名字保持一致,且传入的数据类型要一致
System.out.println("Controller中的save3方法执行");
System.out.println("接收到的数据:"+ Arrays.toString(strs));
}
集合类型参数
POJO包装获取集合
获取集合参数时,要将集合参数包装到一个POJO当中才可以
VO对象用泛型就会抛出索引越界异常
VO
此处用泛型会抛出索引越界异常
package com.ytl.domain;
import java.util.List;
/**
* Value Object 数据对象
* View Object 视图对象
* 这里用来测试集合数据的接收
*/
public class VO {
private List<User> list;
@Override
public String toString() {
return "VO{" +
"list=" + list +
'}';
}
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
}
UserController
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping("/save4")
public void save4(VO userVo){
//形参数组要与传入的数组参数名字保持一致,且传入的数据类型要一致
System.out.println("Controller中的save4方法执行");
System.out.println("接收到的数据:"+ userVo);
}
<form action="${pageContext.request.contextPath}/user/save4" method="post">
<%-- 表明是第几个User对象的name age--%>
<p>第一个user对象</p>
<input type="text" name="list[0].name" /><br />
<input type="text" name="list[0].age" /><br />
<p>第二个user对象</p>
<input type="text" name="list[1].name" /><br />
<input type="text" name="list[1].age" /><br />
<input type="submit" value="提交">
</form>
Ajax获取集合
当使用Ajax提交时,可以指定 contentType为json形式,
那么在方法参数位置使用@RequestBody
可以直接接收集合数据而无需使用POJO进行包装
UserController
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping("/save5")
public void save5(@RequestBody List<User> userList){
System.out.println("Controller中的save5方法执行");
System.out.println("接收到的数据:"+ userList);
}
ajax·jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>ajax测试</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js"></script>
</head>
<body>
<script>
var userList = new Array();
userList.push({name:"张三",age:18});
userList.push({name:"李四",age:36});
userList.push({name:"王五",age:72});
$.ajax({
type: "POST",
url:"${pageContext.request.contextPath}/user/save5",
data:JSON.stringify(userList),
contentType:"application/json;charset=utf-8"
})
</script>
</body>
</html>
此处Web的版本如果是2.x的话,${ } 会被编译成 $%7B %7D
解决方法:
将web的版本改为4.0
<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-app>
静态资源的开启访问
自己配置访问模式
<!-- 在Spring框架当中,开放资源的访问权限-->
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/img/**" location="/img/" />
mapping:映射地址,在服务端找资源时的地址
location:实际地址,资源实际所在的路径
需要开启其他,就再加一个
spring默认配置
<mvc:default-servlet-handler />
代表spring无法找到静态资源时,会将该工作交给原始容器去找(如:Tomcat)
请求数据乱码问题
配置全局乱码过滤器
web.xml
<!-- 配置全局过滤的filter-->
<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>
<!-- 配置全局过滤的filter-->
参数绑定注解@RequestParam
用于请求参数名称与Controller里的业务方法参数名称不统一时,可以用此注解显示的绑定
/save6?name=zhangsan
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping("/save6")
public void save6(@RequestParam(value="name") String userName) {
//形参要与传入的参数名字不一致时要用@RequestParam
System.out.println("Controller中的save6方法执行");
System.out.println("接收到的数据:userName=="+userName);
}
value
:请求参数名称,只有一个参数,该参数名可以省略required
:此在指定请求参数是否必须包含,默认为true,提交时没有此参数会报错defaultValue
:当没有此参数时 ,使用指定的默认值赋值
获取Restful风格的参数
Restful
是一种软件架构风格
,设计风格
,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等
Restful
风格的请求是使用”url+请求方式“
表示一次请求目的的,HTTP协议里面四个表示操作方式的动词如下:
GET
:用于获取资源POST
:用于新建资源PUT
:用于更新资源DELETE
:用于删除资源
例如:
- /user/1
GET
:得到id=1的user - /user/1
DELETE
:删除id=1的user - /user/1
PUT
:更新id=1的user - /user
POST
:新增user
/quick1/zhangsan
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/quick1/{name}",method = RequestMethod.GET)
public void quick1(@PathVariable(value="name") String userName) {
//形参要与传入的参数名字不一致时要用@RequestParam
System.out.println("Controller中的quick1方法执行");
System.out.println("接收到的数据:userName=="+userName);
}
@RequestMapping("/quick1/{name}")
里面的name
必须与@PathVariable
里的value
值统一
跟@RequestMapping
里的method
属性来配合区分请求方式
类型转换器
SpringMVC已经默认提供了一些常用的类型转换器
- 定义转换器类实现
Converter
接口 - 在配置文件中声明转换器
- 在
annotation-driven
中引用转换器
例如:yyyy-MM-dd
格式的日期型字符串转换为Date类型
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/quick2/{date}",method = RequestMethod.GET)
public void quick2(@PathVariable(value="date") Date date) {
System.out.println("Controller中的quick2方法执行");
System.out.println("接收到的数据:date=="+date);
}
自定义的转换器DateConverter
package com.ytl.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String dateStr) {
//将日期字符串转换日期对象,返回
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date parseDate = null;
try {
parseDate = simpleDateFormat.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return parseDate;
}
}
引用转换器
<mvc:annotation-driven conversion-service="conversionService" />
<!-- 声明转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.ytl.converter.DateConverter" />
</list>
</property>
</bean>
获得Servlet相关API
SpringMVC支持使用原始的ServletAPI对象作为控制器方法的参数进行注入,常用的对象如下:
HttpServletRequest
HttpServletResponse
HttpSession
想要什么对象,就在方法中写其的形参,Spring会自动注入
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/quick3/")
public void quick3(HttpServletRequest request, HttpServletResponse response,
HttpSession session) {
System.out.println(request);
System.out.println(response);
System.out.println(session);
}
获取请求头
@RequestHeader
使用它可以获得请求头信息,相当于web阶段的
reqeust.getheader(name)
属性如下:
value
:请求头的名称required
:是否必须携带此请求头
@CookieValue
使用它可以获得指定Cookie的值
属性如下:
value
:指定cookie
的名称required
:是否必须携带此cookie
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/quick4/")
public void quick4(@RequestHeader(value = "User-Agent") String userAgent,
@CookieValue("JSESSIONID") String jSessionId) {
System.out.println("Controller中的quick4方法执行");
System.out.println("请求头的User-Agent:"+userAgent);
System.out.println("cookie中的:JSESSIONID:"+jSessionId);
}
文件上传
文件上传客户端三要素
- 表单项type="
file
" - 表单的提交方式是post
- 表单的
enctype
属性是多部分表单形式,及enctype
="multipart/form-data
"
文件上传原理
- 当form表单修改为多部分表单时,
request.getParameter()
将失效 - 当form表单的
enctype="application/x-www-form-urlencoded"
时,form表单正文内容格式是:key=value&key=value
,默认就是此方式 - 当form表单的
enctype="mutilpart/form-data"
时,请求正文内容就变成多部份形式了
单文件上传步骤
1. 导入fileupload
和io
坐标
<!-- 文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
<!-- 文件上传-->
2. 配置文件解析器
<!-- 文件上传-->
<bean id="commonsMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件总大小-->
<property name="maxUploadSize" value="5242800" />
<!-- 上传单个文件的大小-->
<property name="maxUploadSizePerFile" value="5242800" />
<!-- 上传文件的编码类型-->
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- 文件上传-->
3. 编写单文件上传代码
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/uploadFile1", method = RequestMethod.POST)
public void uploadFile1(String name, MultipartFile uploadFile)
throws IOException {
//单个文件上传
System.out.println("Controller中的uploadFile1方法执行");
System.out.println("name=="+name);
System.out.println("uploadFile=="+uploadFile);
//获取表单上传项里的name属性
String name1 = uploadFile.getName();
//获取文件名称
String originalFilename = uploadFile.getOriginalFilename();
//文件流实例化,参数是一个File对象
uploadFile.transferTo(new File("upload\\"+originalFilename));
System.out.println("name1==="+name1+"\tfileName===="+originalFilename);
}
3. 1编写多文件上传代码
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/uploadFile2", method = RequestMethod.POST)
public void uploadFile2(String name, MultipartFile[] uploadFiles)
throws IOException {
//多个文件上传
System.out.println("Controller中的uploadFile2方法执行");
System.out.println("name=="+name);
for(MultipartFile uploadFile: uploadFiles){
//获取表单上传项里的name属性
String name1 = uploadFile.getName();
//获取文件名称
String originalFilename = uploadFile.getOriginalFilename();
//文件流实例化,参数是一个File对象
uploadFile.transferTo(new File("upload\\"+originalFilename));
System.out.println("name1==="+name1+"\tfileName===="+originalFilename);
}
}
@ResponseBody//此处方法代表不进行页面跳转
@RequestMapping(value = "/uploadFile2", method = RequestMethod.POST)
public void uploadFile2(String name, MultipartFile uploadFile1,MultipartFile uploadFile2)
throws IOException {
//也可以使用该方法
}
JdbcTemplate
开发步骤
- 导入
spring-jdbc
和spring-tx
坐标 - 创建数据库和实体
- 创建jdbc-Template
- 执行数据库操作
<!-- 数据库操作-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- 数据库操作-->
@Test
//调试JdbcTemplate开发步骤
public void test1() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/cartoontest");
dataSource.setUser("root");
dataSource.setPassword("123456");
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//设置数据源对象,知道数据库在哪
jdbcTemplate.setDataSource(dataSource);
//执行操作,update添加,删除,修改;query:用于查询
int rows = jdbcTemplate.update("insert into admin values(3, ?, ?,?)",
"admin3", "123456", "汤姆");
System.out.println(rows);
// jdbcTemplate.query("select * from admin",);
}
spring产生JdbcTemplate对象
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 加载外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 此处name是当前类set方法去掉set字且首字母小写的结果-->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
JdbcTemplateCRUDTest.java
package com.ytl.test;
import com.ytl.domain.Admin;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)//利用导入的包进行测试
@ContextConfiguration("classpath:applicationContext.xml")//导入测试所用的配置文件
public class JdbcTemplateCRUDTest {
@Autowired//自动在spring容器寻找类型为JdbcTemplate的变量
private JdbcTemplate jdbcTemplate;
@Test
public void testUpdate(){
int rows = jdbcTemplate.update("update admin set trueName = ? where id = ?", "杰克", 4);
System.out.println(rows);
rows = jdbcTemplate.update("delete from admin where id = ?", 4);
System.out.println(rows);
}
@Test
public void testQueryAll(){//查询全部
RowMapper<Admin> rowMapper = new BeanPropertyRowMapper<Admin>(Admin.class);
List<Admin> queryResult = jdbcTemplate.query("select * from admin", rowMapper);
System.out.println(rowMapper);
System.out.println(queryResult);
}
@Test
public void testQueryOne(){//查询单个
RowMapper<Admin> rowMapper = new BeanPropertyRowMapper<Admin>(Admin.class);
Admin admin = jdbcTemplate.queryForObject("select * from admin where id = ?",
rowMapper, 1);
System.out.println(rowMapper);
System.out.println(admin);
}
@Test
public void testQueryCount(){//查询总数
Long aLong = jdbcTemplate.queryForObject("select count(*) from admin",
Long.class);
System.out.println(aLong);
}
}
SpringMVC拦截器
HandlerInterceptor
<!-- 5. 配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 对那些资源进行拦截操作-->
<mvc:mapping path="/**" />
<bean class="com.ytl.interceptor.MyInterceptor1" />
</mvc:interceptor>
</mvc:interceptors>
preHandle方法
返回只是一个布尔值,为true时放行
在目标方法执行之前执行
可以在此方法中 请求转发 或 重定向 到其它资源
请求转发
request.getRequestDispatcher("").forward(request, response);
重定向
response.sendRedirect("");
postHandle方法
在目标方法执行之后 视图对象返回之前执行
有 ModelAndView 参数就可以修改返回的数据和视图
afterCompletion方法
在流程结束后执行
可以封装异常,也可以跳转
多个拦截器
顺序是由
spring-mvc.xml
中的配置顺序
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession httpSession = request.getSession();
Object user = httpSession.getAttribute("user");
if(user instanceof User){
// request.getRequestDispatcher(request.getRequestURI()).forward(request, response);
System.out.println("存在user");
System.out.println(request.getRequestURI());
}else {
System.out.println("不存在user");
response.sendRedirect(request.getContextPath()+"/login.jsp");
return false;
}
//放行,访问资源
return true;
}
<mvc:interceptor>
<!-- 对那些资源进行拦截操作-->
<mvc:mapping path="/**" />
<!-- 对那些资源取消拦截操作-->
<mvc:exclude-mapping path="/user/login.do" />
<bean class="com.ytl.interceptor.MyInterceptor1" />
</mvc:interceptor>
Spring MVC的异常处理
<!--4、配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="defaultError" />
<property name="exceptionMappings">
<map>
<entry key="java.lang.ClassCastException" value="error1" />
<entry key="com.ytl.exception.MyException" value="error2" />
</map>
</property>
</bean>
<!--4、配置自定义异常处理器-->
<bean class="com.ytl.resolver.MyExceptionResolver" />