SpringMVC框架
第一章SpringMVC概述
1.1 SpringMVC基本说明
SpringMVC是基于spring的,是spring中的一个模块,做web开发使用的,springmvc叫做spring web mvc说明他是spring的核心技术,做web开发,springmvc内部是使用mvc架构模式。
springMVC是一个容器,管理对象的,使用IOC核心技术。springmvc管理界面层中的控制器对象。
springMVC底层也是Servlet。以Servlet为核心,接受请求,处理请求。显示处理结果给用户。
处理用户的请求:
用户发起请求-----SpringMVC-----Spring-----Dao-----MyBatis-----MySQL数据库
1.2 SpringMVC中的核心Servlet–DispatcherServlet
DispatcherServlet是框架一个servlet对象。负责接收请求,响应处理结果。
DispatcherServlet的父类是HttpServlet
DispatcherServlet也叫做前端控制器(front controller)。
SpringMVC是管理控制器对象,原来没有SpringMVC之前使用Servlet作为控制器对象使用。现在通过SpringMVC容器创建一种叫做控制器的对象,代替Servlet行使控制器的角色。功能。
SpringMVC主要使用注解的方式,创建控制器对象,处理请求。
web.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>springmvc</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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
springmvc.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">
<!--springmvc的配置文件-->
<!--声明组件扫描器-->
<context:component-scan base-package="com.cs.controller"/>
</beans>
controller
package com.cs.controller;
import com.sun.jmx.snmp.SnmpUnknownModelLcdException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @Controller:创建控制器对象
* 控制器:叫做后端控制器,自定义的类处理请求
* 位置:在类的上面,表示创建此类的对象,对象放在springmvc的容器中
*/
@Controller
public class MyController {
/**
* @RequestMapping:请求映射
* 属性:value 请求中的url地址,唯一值,以“/”开头
* 位置:在方法上(必须的)在类上面
* 作用:把指定的请求,交给指定的方法处理,等同于url-pattern
* @return:ModelAndView表示本次请求的处理结果(数据和视图)
* Model:表示数据
* View:表示视图
*/
@RequestMapping(value = "/some.do")
public ModelAndView doSome(){
//使用该方法处理请求,能处理请求的方法叫做控制器方法
System.out.println("执行了MyController的doSome方法");
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了some.do请求");
mv.addObject("fun","执行了doSome方法");
//指定显示数据的视图,视图的完整路径
mv.setViewName("/show.jsp");
//返回结果
return mv;
}
}
show.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<html>
<head>
<title>show</title>
</head>
<body>
/show.jsp,显示request作用域中的数据<br/>
<h3>msg数据:${msg}</h3>
<h3>fun数据:${fun}</h3>
</body>
</html>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>第一个springmvc</title>
</head>
<body>
<a href="some.do">发起some.do的请求</a>
</body>
</html>
1.3 SpringMVC请求的处理过程
简单的处理过程:
用户发起请求some.do----->Tomcat接受了请求----->DispatcherServlet----->分配MyController(doSome()返回mv对象)----->mv显示给用户了。
1.4
用户发起some.do—DispatcherServlet(Servlet接受请求)—转给MyController
public class DispatcherServlet extends HttpServlet{
public void service(HttpServletRequest request,HttpServlet response){
if("some.do".equals(request.getURL())){
//从容器中获取MyController
MyController c = ctx.getBean("some");
c.doSome();
}else if("other.do".equals(request.getURL())){
OtherController c = ctx.getBean("other");
c.doOther();
}
}
}
1.5 web开发中配置文件的说明
-
web.xml部署描述符文件,给服务器(tomcat)
作用:服务器在启动的时候,读取web.xml,根据文件中的声明创建各种对象,根据文件中的声明知道请求和servlet等对象的关系。
-
框架的配置文件:springmvc的配置文件
作用:声明框架创建的项目中的各种对象,主要是创建Controller对象的
配置文件的加载顺序和功能
-
tomcat服务器启动,读取web.xml.根据web.xml文件中的说明,创建对象。
<servlet> <servlet-name>springmvc</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> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
创建DispatcherServlet的对象,会执行init方法,在init方法中会执行springmvc容器对象创建WebApplicationContext ctx = new ClassPathXmlApplicationContext(“classpath:springmvc.xml”)
-
springmvc框架,new ClassPathXmlApplicationContext() 读取springmvc的配置文件
<!--springmvc的配置文件--> <!--声明组件扫描器--> <context:component-scan base-package="com.cs.controller"/> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean>
使用组件扫描器base-package=“com.cs.controller”,遍历controller包中的所有类,MyController类,找到这个类中的@Controller,@RequestMapping注解,就能创建MyController对象。知道some.do的请求是执行doSome()方法
以上1,2都是项目启动的过程,没有执行任何的用户请求
-
用户发起请求some.do—DispatcherServlet
DispatcherServlet里面有WebApplicationContext。WebApplicationContext里面有MyController对象。
请求some.do,DispatcherServlet就知道是MyController处理的。
第二章 SpringMVC注解式开发
2.1 @RequestMapping注解的使用
@RequestMapping:请求映射
属性:value 请求中的url地址,唯一值,以“/”开头
位置:在方法上(必须的)在类上面作为模块名称
作用:把指定的请求,交给指定的方法处理,等同于url-pattern
@Request(value = "/some.do",method = RequestMethod.POST)
public ModelAndView doOther(){}
对请求提交方式的定义
序号 | 请求方式 | 提交方式 |
---|---|---|
1 | 表单请求 | 默认GET,可以指定POST |
2 | Ajax请求 | 默认GET,可以指定POST |
3 | 地址栏请求 | GET请求 |
4 | 超链接请求 | GET请求 |
5 | src资源路径请求 | GET请求 |
2.2 接收请求中的参数
对应HttpServletRequest,HttpServletResponse,HttpSession只需要在控制器方法的形参列表中,定义就可以了,框架会给参数赋值,在控制器方法内可以直接使用request,response,session参数。
400:http status,表示客户端异常。主要是发生在用户提交参数过程中。
接收请求中的参数:逐个接收,对象接收
2.2.1 逐个接收
逐个接收:请求中的参数名和控制器方法的形参名一样。按照名称对应接受参数
<p>逐个接收请求参数</p>
<form action="receive-property.do" method="post">
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="提交参数">
</form>
Controller接收参数
@RequestMapping(value = "/receive-property.do")
public ModelAndView doPropertyParam(String name,Integer age){
2.2.2 接收参数的问题
-
参数最好使用包装类型,例如Integer,能接收空值情况,接受的是null
-
框架可以使用String到int,long,float,double等类型转换
-
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> <!--强制请求(request)对象使用encoding的编码格式--> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> <!--强制应答(response)对象使用encoding的编码格式--> <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>
2.2.3 请求中参数名和形参名不一样,使用@RequestParam
/* 形参值与请求值不一致
* @RequestParam:解决名称不一致问题
* 属性:value 请求中的参数名称
* required boolean类型的,默认是true
* true:请求中必须有此参数,没有报错
* false:请求中可以没有此参数。
* 位置:在形参定义的前面
*/
@RequestMapping(value = "/receive-param.do")
public ModelAndView doReceiveParam(@RequestParam(value = "rname",
required = false) String name,
@RequestParam(value = "rage",
required = false) Integer age)
2.2.4 对象接收
对象接收:在控制器方法的形参是java对象,使用java对象的属性接收请求中的参数值
要求:java对象的属性值名和请求中的参数名一样
例子:
public class Student {
private String name;
private Integer age;
//ser|get方法
@RequestMapping(value = "/receive-object.do")
public ModelAndView doReceiveObject(Student student){
System.out.println("执行了MyController的doReceiveObject方法"+student);
ModelAndView mv = new ModelAndView();
mv.addObject("myname",student.getName());
mv.addObject("myage",student.getAge());
mv.setViewName("show");
return mv;
}
2.3 控制器方法的返回值
控制器方法的返回值表示本次请求的处理结果,返回值有ModelAndView,String,void,Object
请求的处理结果包含:数据和视图
2.3.1 ModelAndView数据和视图
请求结果有数据和视图,使用MOdelAndView最方便
数据:存放request作用域
视图:执行forward转发操作
2.3.2 String视图
框架对返回值是string,执行的是forward转发操作
视图可以表示为完整视图路径,或者视图的逻辑名称
@RequestMapping(value = "/return-string-view.do")
public String doReturnStringView(HttpServletRequest request,String name, Integer age){
System.out.println("执行了MyController的doReturnStringView="+ name +",age=" + age);
//返回结果,forward,转发到show.jsp
//逻辑名称,需要配置视图解析器
request.setAttribute("myname",name);
request.setAttribute("myage",age);
return "show";
}
@RequestMapping(value = "/return-string-view2.do")
public String doReturnStringView2(HttpServletRequest request,String name, Integer age){
System.out.println("执行了MyController的doReturnStringView2="+ name +",age=" + age);
request.setAttribute("myname",name);
request.setAttribute("myage",age);
//完整视图路径,不能使用视图解析器
return "/WEB-INF/view/show.jsp";
}
2.3.3 void 没有数据和视图
void:没有数据和视图,可以使用HttpServletResponse对象输出数据,响应ajax请求。
/**
* 控制器方法返回时void,响应ajax请求,使用HttpServletResponse输出数据
*/
@RequestMapping("/return-void-ajax.do")
public void returnVoidAjax(HttpServletResponse response,String name, Integer age) throws IOException {
System.out.println("处理void返回类型,name="+ name + ",age=" + age);
//调用service得到结果对象
Student student = new Student();
student.setName(name + "同学");
student.setAge(age);
//把对象转为json
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(student);
System.out.println("服务器端对象转为的json===="+json);
//输出json,响应ajax
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>请求方式</title>
<script type="text/javascript" src="js/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function () {
//绑定事件
$("#btnAjax").on("click",function () {
$.ajax({
url: "return-void-ajax.do",
data: {
name:"lisi",
age:20
},
dataType:"JSON",
success:function(resp){
alert("resp=="+resp.name+"==="+resp.age);
}
})
})
})
</script>
</head>
<body>
<button id="btnAjax">发起ajax请求</button>
</body>
</html>
2.3.4 Object
返回Student表示数据,还是视图。所以控制器方法返回对象Object,用来响应ajax请求
返回对象Object,可以是List,Student,Map,String,Integer…这些都是数据,而ajax请求需要的就是数据。在ajax请求中,一般需要从服务器返回的是json格式的数据,经常要处理java对象到json的转换,而且还需要输出数据响应ajax请求。框架提供了处理java对象到json转换,还是数据输出工作。
2.3.4.1 HttpMessageConverter消息转换器
HttpMessageConverter接口,作用是:
1)实现请求的数据转为java对象
2)把控制器方法返回的对象转为json,xml,text,二进制等不同格式的数据。
public interface HttpMessageConverter<T> {
/**
作用:检查var1这个类型的对象,能否转为mediayType表示的数据格式
如果能转为var2表示的类型,返回true,返回true调用read()
*/
boolean canRead(Class<?> var1, @Nullable MediaType var2);
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}
默认情况下:springmvc使用了HttpMessageConveter接口的4个实现类。包括了StringHttpMessageConverter
需要在springmvc的配置文件中,加入注解驱动的标签mvc:annotation-driven.加入这个标签后,springmvc项目启动后,会创建HttpMessageConverter接口的7个实现类对象,包括StringHttpMessageConverter和Mappingglackson2HttpMessageConverter。
2.3.4.2 @ResponseBody
@ResponseBody注解的作用,就是把student转换后的json通过HttpServletResponse对象输出给浏览器。
//输出json,响应ajax
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
@ResponseBody注解作用就是上面代码的实现
2.3.4.3 控制器方法返回对象转为的步骤
- pom.xml加入jackson依赖,springmvc框架,默认处理json就是使用jackson
- 在springmvc的配置文件中,加入注解驱动的标签mvc:annotation-driven
- 在控制器方法的上面加入@ResponseBody注解,表示返回值数据输出到浏览器。
2.4 静态资源处理
2.4.1 tomcat的default servlet
tomcat安装目录/conf/web.xml
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
default叫做默认servlet,作用:
1、它提供静态资源的处理
2、它处理所有未映射到其他请求的请求过程
2.4.2 中央调度器设置“/”
使用斜杠“/”,导致中央调度器成为了默认的default servlet。
需要处理静态资源和其他的未映射的请求。默认中央调度器没有处理
静态资源的控制器对象,所以静态资源都是404。some.do这个请求有MyController对象,所以能访问
如果项目中,中央调度器设置了“/“,动态资源能访问,静态资源不能访问。
需要处理静态资源的访问工作。
2.4.3 第一种方式处理静态资源
在springmvc的配置文件中加入mvc:default-servlet-handler标签,springmvc框架会在项目运行时,加入DefaultServletHttpRequestHandler对象,让这个对象处理静态资源的访问
<!--springmvc的配置文件-->
<!--声明注解驱动
default-servlet-handler和@RequestMapping使用有冲突
-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--声明静态资源的第一种处理方式-->
<mvc:default-servlet-handler/>
优点:解决方式简单
缺点:依赖tomcat服务器提供的能力。
2.4.4 第二种静态资源的处理方式
在springmvc配置文件中加入一个mvc:resources标签,框架会创建ResourcesHttpRequestHandler控制器对象,使用这个对象处理静态资源的访问。不依赖tomcat服务器。推荐使用。
<!--springmvc的配置文件-->
<!--声明注解驱动
default-servlet-handler和@RequestMapping使用有冲突
-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--声明静态资源的第二种处理方式mapping:访问静态资源的url地址,可以使用通配符(**)
**:表示任意的目录和目录的资源名称
location:静态资源在项目中的位置,不要使用/WEB-INF目录
-->
<mvc:resources mapping="/static/**" location="/static/"/>
2.5 JSR303校验
数据校验:如何校验?注解?
- 使用JSR303验证标准
- 加入hibernate validator验证框架
- 在springmvc配置文件中添加
- 需要在bean的属性上添加对应的注解
- 在目标方法bean类型的前面添加@Valid注解
验证出错转向哪一个页面?
错误消息如何显示,如何把错误消息进行国际化
2.6 RestFul风格
RestFul就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
功能
- 资源:互联网所有的事物都可以被抽象为资源
- 资源操作:使用POST DELETE、PUT、GET,使用不同方法对资源进行操作。
- 分别对应添加,删除,修改,查询。
传统方式操作资源:通过不同的参数来实现不同的效果!方法单一,post和get
- http://127.0.0.1/item/queryItem.action?id=1查询,GET
- http://127.0.0.1/item/saveItem.action新增,POST
- http://127.0.0.1/item/updateItem.action更新,POST
- http://127.0.0.1/item/deleteItem.action?id=1删除,GET或POST
**使用RestFul操作资源:**可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同
- http://127.0.0.1/item/1查询,GET
- http://127.0.0.1/item新增,POST
- http://127.0.0.1/item更新,PUT
- http://127.0.0.1/item/1删除,DELETE
测试
@Controller
public class MyController {
@RequestMapping("/index.do/{a}/{b}")
public String restful(@PathVariable int a,@PathVariable int b, Model model){
int res = a+b;
model.addAttribute("msg","结果为:"+ res);
return "test";
}
}
2.7 json
2.7.1 jackson
加入依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
需要注意使用ObjectMapper对象需要使用jackson2.10.0以上的版本
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
@ResponseBody
public String json() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User("小艾1号", 3, "男");
String string = objectMapper.writeValueAsString(user);
return string;
}
乱码问题解决
-
在注解@RequestMapping中加入参数produces = “application/json;charset=utf-8”
-
在配置文件中加入:
<!--JSON乱码问题配置--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="failOnEmptyBeans" value="false"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
手写一个json的工具类JsonUtils
package com.cs.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtils {
public static String getJson(Object object){
return getJson(object,"yy-MM-dd HH:mm:ss");
}
public static String getJson(Object object,String dataFormat){
ObjectMapper objectMapper = new ObjectMapper();
//不使用时间戳的方式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//自定义日期格式
SimpleDateFormat sdf = new SimpleDateFormat(dataFormat);
objectMapper.setDateFormat(sdf);
String string = null;
try {
string = objectMapper.writeValueAsString(object);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
2.7.2 fastjson
导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
@RequestMapping(value = "/j3")
@ResponseBody
public String json2(){
List<User> list = new ArrayList<>();
list.add(new User("小艾1号", 3, "男"));
list.add(new User("小艾2号", 3, "男"));
list.add(new User("小艾3号", 3, "男"));
list.add(new User("小艾4号", 3, "男"));
String string = JSON.toJSONString(list);
return string;
}
2.8 Ajax
Ajax不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的web应用程序的技术。
jquery向服务器发送一个ajax请求后,可以返回多种类型的数据格式,包括:html,xml,json,text等。
Ajax的标准格式:
$.ajax({
url:"http://www.test.com", //请求的url地址
dataType:"json", //返回格式为json async:true,//请求是否异步,默认为异步,这也是ajax重要特性 data:{"id":"1","name":"名字"}, //参数值 type:"GET", //请求方式 beforeSend:function(){ //请求前的处理 },
success:function(req){ //请求成功时处理 },
complete:function(){ //请求完成的处理 },
error:function(){ //请求出错处理 }
});
举例:使用Ajax实现用户登录校验
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/js/jquery-1.12.4.js"></script>
<script>
function a1(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"name":$("#name").val()},
success:function (data) {
if (data.toString()==='ok'){
$("#userInfo").css("color","green");
}else{
$("#userInfo").css("color","red");
}
$("#userInfo").html(data);
}
})
}
function a2(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"pwd":$("#pwd").val()},
success:function (data) {
if (data.toString()==='ok'){
$("#pwdInfo").css("color","green");
}else{
$("#pwdInfo").css("color","red");
}
$("#pwdInfo").html(data);
}
})
}
</script>
</head>
<body>
<p>
用户名:<input type="text" id="name" οnblur="a1()">
<span id="userInfo"></span>
</p>
<p>
密码:<input type="text" id="pwd" οnblur="a2()">
<span id="pwdInfo"></span>
</p>
</body>
</html>
@RequestMapping("/a3")
public String s3(String name,String pwd){
String msg = "";
if (name!=null) {
if ("admin".equals(name)) {
msg = "ok";
}else{
msg = "用户名有误!";
}
}
if (pwd!=null) {
if ("123456".equals(pwd)) {
msg = "ok";
}else{
msg = "密码有误!";
}
}
return msg;
}
2.9 拦截器
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自定义一些拦截器来实现特定的功能。
**过滤器和拦截器的区别:**拦截器是AOP思想的具体应用。
拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/image/js是不会进行拦截的。
2.9.1 自定义拦截器
想要自定义拦截器,必须实现HandlerIntercepot接口。
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//放行:判断什么情况下登录
/**
* 1、session有值
* 2、登陆页面也会放行
*/
if (request.getRequestURI().contains("Login")){
return true;
}
if (session.getAttribute("userLoginInfo")!=null){
return true;
}
//判断什么情况下没有登录
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.cs.controller"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.cs.config.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
2.10 文件上传和下载
导入依赖
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
SpringMVC使用表单文件上传需要设置enctype为multipart/form-data;浏览器就会采用二进制的方式来处理表单数据。
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload"/>
</form>
SpringMVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolve实现的。配置文件上传的id必须是multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--请求的编码格式,必须和jsp的pageEncoding属性一致-->
<property name="defaultEncoding" value="utf-8"/>
<!--上传文件大小上限,单位为字节(10485760=10M)-->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
两种下载方式
@RestController
public class MyController {
@RequestMapping("/upload1")
public String file(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//获取文件名
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接回到首页
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名:"+uploadFileName);
//上传路径保存
String path = request.getServletContext().getRealPath("upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+ realPath);
InputStream is = file.getInputStream();//文件输入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));//文件输出流
//读取写出
int len = 0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
/**
* 方式二:采用file.transferTo 来保存上传的文件
*/
@RequestMapping("upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+ realPath);
//通过CommonsMultipartFile的方式直接写文件
file.transferTo(new File(realPath + "/" + file.getOriginalFilename()));
return "redirect:/index.jsp";
}
}
第三章 SSM整合
3.1 SSM思路
SSM思路:Springmvc+Spring+MyBatis(IBatis),所以有人叫做SSI整合。
SSM整合是使用三个框架的优势功能。三个框架对应的三层架构的三层。SpringMVC是视图层,Spring是业务层,MyBatis持久层。
SSM整合,需要把对象交给容器管理,让容器去创建项目中要使用的java对象。现在有两个容器。
第一个是Spring容器:Spring容器是管理service和dao等对象的。是业务层对象的容器。
第二个是SpringMVC容器:管理控制器对象的。是视图层对象。
SSM整合就是把对象交给容器管理。两个容器共存。各自负责管理不同的对象。把对象声明到配置文件中,让两个容器创建对象。spring创建service,dao,springmvc创建controller。
3.2 容器的创建
Spring容器的创建:在web.xml声明了监听器ContextLoaderListener,这个功能框架写好了。功能是创建spring的容器对象WebApplicationContext。在创建WebApplicationContext对象时,读取spring的配置文件,读取文件的时候,遇到bean标签或者注解,就能创建service,dao等对象,放到容器中。
SpringMVC容器:在web.xml声明了中央调度器DisPacherServlet。在这个servlet的init()方法中,创建了容器对象WebApplicationContext,在创建WebApplicaitonContext对象,读取springmvc的配置文件,读取了文件的时候,遇到@Controller注解,创建控制器controller对象,放到容器中。
内存中,创建对象
WebApplicationContext spring = new WebApplicationContext();//spring–map(service,dao)
WebApplicationContext springmvc = new WebApplicationContext();//springmvc–map(controller)
SpringMVC容器和Spring容器的关系:设计上springMVC容器对象是Spring容器的子容器
Spring是父容器。springmvc子容器,相当于java中的继承关系
3.3 SSM整合开发步骤
- 使用的student表(id,name,age)
- 创建maven web项目
- 修改pom.xml加入依赖:spring,springmvc,mybatis,mybatis-spring,MySQL驱动,druid,jackson
- 写web.xml:声明容器对象
- 声明spring的监听器ContextLoaderListener:创建spring的容器对象,创建service,dao对象
- 声明springmvc的中央调度器DispatcherServlet:创建springmvc容器对象,创建controller对象
- 声明字符集的过滤器CharacterEncodingFilter,解决post请求乱码的问题
- 创建程序中的包,dao,service,controller,entity
- 写spring,springmvc,mybatis配置文件
- 写java代码,实体类,dao接口和mapper文件,service类,controller类,使用注解声明对象和赋值
- 创建视图文件,各种jsp
pom.xml
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<!--Spring JDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<!--Spring AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<!--MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--MyBatis整合Spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--MySQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--Druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--JSTL-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
</dependency>
<!--jackson依赖-->
<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>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
<!--静态资源导出问题-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
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">
<!--声明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:conf/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--声明字符集过滤器-->
<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>
<!--加载静态资源-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
spring-dao.xml
<!-- 配置整合mybatis -->
<!-- 1.关联数据库文件 -->
<context:property-placeholder location="classpath:database.properties"/>
<!-- 2.数据库连接池 -->
<!--数据库连接池
dbcp 半自动化操作 不能自动连接
c3p0 自动化操作(自动的加载配置文件 并且设置到对象里面)
-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
<property name="username" value="${jdbc.username}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 3.配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置MyBatis全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
<!--解释 :https://www.cnblogs.com/jpfss/p/7799806.html-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.cs.dao"/>
</bean>
spring-service.xml
<!--扫描service下的包-->
<context:component-scan base-package="com.cs.service"/>
<!--将我们的所有业务类,注入到Spring,可以通过配置,或者注解实现-->
<bean id="BookServiceImpl" class="com.cs.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!--声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--aop事务支持-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务的传播特性:new propagation-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.cs.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
spring-mvc.xml
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解驱动 -->
<mvc:annotation-driven />
<!-- 2.静态资源默认servlet配置-->
<mvc:default-servlet-handler/>
<!-- 3.配置jsp 显示ViewResolver视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.cs.controller" />
</beans>
mybatis-config
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.cs.pojo"/>
</typeAliases>
<mappers>
<mapper resource="com/cs/dao/BookMapper.xml"/>
</mappers>
</configuration>
mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cs.dao.BookMapper">
<insert id="addBook" parameterType="Books">
insert into books(bookName,bookCounts,detail)
values(#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteBook" parameterType="int">
delete from books
where bookID = #{bookID};
</delete>
<update id="updateBook" parameterType="Books">
update books set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
where bookID = #{bookID};
</update>
<select id="queryBookById" resultType="Books">
select * from books
where bookID = #{bookID};
</select>
<select id="queryAllBook" resultType="Books">
select * from books;
</select>
<select id="queryBookByName" resultType="Books">
select * from books
where bookName = #{bookName};
</select>