springmvc 源码
springmvc 流程图
Springmvc 三大组件(组成)部分?
- 处理器映射器,将请求路径映射到我们的适配器
- 处理器映射器,适配合适的处理器,传递参数,并接收执行结果
- 试图解析器,根据结果响应不同的页面
springmvc 笔记
服务器三层架构:表现层,业务层,持久层
springmvc属于表现层框架
mvc:
model 模型:javaBean
view 视图:jsp
controller 控制器:servlet
处理请求,转发
springmvc与struts2的区别
Springmvc的入口是Servlet ,Struts2的入口是Filter
springmvc的JSTL执行效率高,struts2的OGNL开发效率高
Maven创建项目时过慢,不下载插件方法
在new Module 时,添加键值对
key:archetypeCatalog value:internal
笔记1
添加maven基本依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- <maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>-->
<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>
<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.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
web.xml配置,在项目启动时加载springmvc.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<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>
<load-on-startup>1</load-on-startup> <!--加载顺序-->
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> <!-- 拦截路径 -->
</servlet-mapping>
</web-app>
springmvc.xml
context:注解 beans:spring基本 mvc:springmvc基本
<?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">
<!--开启注解扫描-->
<context:component-scan base-package="com.zxit"></context:component-scan>
<!--视图解析器对象-->
<!--根据执行方法的返回值,来找对应的方法-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/> <!--有返回,直接来到这个目录找-->
<property name="suffix" value=".jsp"/> <!--来到这个目录,找jsp后缀-->
</bean>
<!--开启SpringMVC框架注解支持-->
<mvc:annotation-driven/>
</beans>
#sayHello.java
//控制器
@Controller
public class HelloSprintMVC {
//请求映射
@RequestMapping("/sayHello")
public String sayHello(){
System.out.println("say Hello SpringMVC zx");
return "success";
}
}
如果想通过 return 访问 文件夹下的 jsp , 可以 return “page/aa.jsp"
笔记2 :请求
注解:
@Controller 控制器注解,默认单例
@RequestMapping 请求映射 用法:@RequestMapping(path="/sayHello") 该注解可以作用在类上或者方法上,如果在类上就是多级路径。
path = value ,当RequestMapping 里只有一个参数时,可以不写value。
method 请求方式:设定方法访问方式: @RequestMapping(path="/sayHello",method={RequestMethod.POST})
params 必须传入指定名称参数:@RequestMapping(path="/sayHello",params={"name"}),表示请求必须传入一个指定的name参数,如果没有,则不执行该方法。或者params={"name=haha"} 要求必须传入一个值为haha的name属性,没有则不执行方法。
传递请求参数 :
请求地址:http://localhost:8080/项目/dis?username=xx&userpass=xx
@RequestMapping(value = "/dis")
public String dis(String username,String userpass){
System.out.println("有username,userpass的方法执行了");
return "success";
}
请求参数封装成实体
userdata.jsp
<head>
<title>用户信息-请求参数封装实体</title>
</head>
<body>
<form action="UserData/save" method="get">
学生姓名:<input type="text" name="studentName"/><br>
学生年龄:<input type="text" name="studentAge"/><br>
学生所属老师:<input type="text" name="studentTeacher.teacherName"/><br>
学生所属老师年龄:<input type="text" name="studentTeacher.teacherAge"/><br>
<input type="submit" value="保存"/><br>
</form>
</body>
Student.java
public class Student {
private String studentName;
private String studentAge;
private Teacher studentTeacher;
...get,set,toString方法
}
Teacher.java
public class Teacher {
private String teacherName;
private String teacherAge;
...get,set,toString方法
}
控制器类
@Controller
@RequestMapping(value = "/UserData")
public class UserDataSpringMVC {
@RequestMapping(value = "/save")
public String save(Student stu){
System.out.println(stu);
return "success";
}
}
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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
获得原生Servlet对象
@Controller
@RequestMapping(value = "/UserData")
public class UserDataSpringMVC {
@RequestMapping(value = "/select")
public String select(HttpServletRequest request,HttpServletResponse response){
System.out.println(request,response);
return "success";
}
}
注解
@Controller 控制层注解
@RequestMapping 请求地址映射注解
@RequestMapping(value = "/save")
public String save(Student stu){
System.out.println(stu);
return "success";
}
@RequestParam 请求参数映射(传入name属性,赋值到username)
@RequestMapping(value = "/RequestParam")
public String RequestParam(@RequestParam(value = "name") String username){
System.out.println("anno testReqeust run。。"+username);
return "success";
}
<a href="anno/RequestParam?name=testname" >RequestParamTest</a>
@RequestParam(value="pages",required=false,defaultValue="xx") Integer page
// 如果传递了pages 参数,就用pages 参数,如果没有,则使用默认值xx
required=false 允许不传递该参数
defaultValue=xx 默认值
@RequestBody 用于获得请求体内容,可获得key/value内容
get方法不适用,因为get把参数都放在了地址里面
而post方法,会将参数做成key/value形式封装到请求里面
@RequestMapping(value = "/RequestBody")
public String RequestBody(@RequestBody String body){
System.out.println("ReqeustBody "+body);
return "success";
}
RequestBody 获取请求体(get请求不适用)
<form action="anno/RequestBody" method="post">
用户名:<input type="text" name="username" ><br>
密码:<input type="text" name="userpass" ><br>
<input type="submit" value="提交">
</form>
Console: ReqeustBody username=22&userpass=22
@ResponseBody 响应处理,用在返回类型处
将json转成User对象,最后又将User对象转成json返回出去
public @ResponseBody User testAjax(@RequestBody User user ){
return user;
}
@PathVaribale 请求参数占位符
restful风格:请求地址都一致,根据不同的请求方式来选择方法 (例:post,get,put)
@RequestMapping(value = "/PathVaribale/{sid}")
public String PathVariable(@PathVariable(name = "sid") String id ){
System.out.println("PathVariable "+id );
return "success";
}
PathVariable的name属性需要与RequestMapping的value属性{}内容一致,形参id只是用来存放sid传过来内容的,命名意义不大
<a href="anno/PathVaribale/1">PathVariable</a>
@RequestHeader 获取请求头
@RequestMapping(value = "/RequestHeader/{sid}")
public String RequestHeader(@RequestHeader(value = "Acccpt") String head ){
System.out.println("RequestHeader "+hear );
return "success";
}
<a href="anno/RequestHeader">RequestHeader</a>
@CookieValue 获取当前会话的cookie,返回当前cookie值
@RequestMapping(value="/CookieValue")
public String cookieValue( @CookieValue(value="JSESSIONID") String cookieValue){
System.out.pringln(cookieValue);
return "success";
}
<a href="anno/cookieValue">CookieValue</a>
@ModelAttribute 模型参数 ,在执行请求前,必须提前执行的方法
该方法可以设置成和form提交类型一样的返回类型,可提前对提交数据校验
@ModelAttribute
public void befor(){
System.out.println("当前请求前,提前执行的方法");
}
使用Model 调用request,执行如下操作后,就可以在jsp页面通过request获取user
@RequestMapping("/selectMethod")
public String select(Model model){
System.out.pringln("查询数据库");
User user = new User("姓名","性别");
model.addAttribute("user",user);
return "success";
}
笔记3: 响应
复习servlet
执行对应的方法后,根据返回值会来到springmvc.xml中找到jsp页面路径,打开对应的jsp
例如程序返回success,那么就会去/WEB-INF/pages/success.jsp。如果返回ok,则找ok.jsp
#springmvc.xml
<!--视图解析器对象-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/> <!--有返回,直接来到这个目录找-->
<property name="suffix" value=".jsp"/> <!--来到这个目录,找jsp后缀-->
</bean>
class : ModelAndView 跳转和视图类 详解
指定返回值与返回页面,作用与Model类加上return “success" 是一样,其实Model类底层就是调用ModelAndView
public ModelAndView testModelAndView(){
//创建ModelAndView对象
ModelAndView model = new ModelAndView();
User user = new User("测试",22);
//把user对象存储到mv对象中,也间接性的存到了request对象中
model.addObject("user",user);
//指定返回值(跳转页面参数)
model.setViewName("success");
return model;
}
设置springmvc拦截器不拦截js,css,image等资源,因为springmvc-->DispatcherServlet拦截器会拦截所有请求,
那么也包括了资源文件的url路径,要想避开资源文件,就在springmvc.xml中配置
<!--前端控制器-->
<!--设置静态资源不拦截-->
<!--此处主要写图片文件夹啊,js,css等-->
<mvc:resources mapping="/js/**" location="/js/**"/>
json字符串和JavaBean对象互相转换所需的jar包
<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-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
按钮触发ajax事件,异步请求数据,返回并显示
@ResponseBody 是指将返回数据封装成json
/**
* 模拟异步请求
* 因为导入json转bean的jar包
* 所以会自动的将json传过来的数据封装到user中
* @param user
*/
@RequestMapping(value = "/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax执行。。。1");
System.out.println(user);
return user;
}
<script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
<script>
$(function(){
$("#testAjax").click(function () {
//alert("hello btn");
$.ajax({
url:"user/testAjax", //请求地址
contentType:"application/json;charset=UTF-8", //传输数据类型
data:'{"userName":"admin","userPass":"123"}', //要传输的数据
dataType:"json", //返回值类型
type:"post", //请求方式
success:function(data){ //data表示服务端响应的数据
alert("hello btn");
alert(data.userName);
alert("单价"+data.userPrice);
}
});
});
});
</script>
<button id="testAjax">testAjax测试</button>
文件上传
1.form表单的enctype取值必须是:multipart/form-data
2.method属性的取值必须是Post
3.提供一个文件选择域<input type="file"/>
springmvc配置文件解析器(springmvc.xml)
<!--配置文件解析器,id名不可改,必须用这个-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"></property>
</bean>
上传方法参数中的MultiparFile 的变量名,必须与form表单的<input type="file"/>name名一致
@RequestMapping(value = "/fileUpload")
public String fileUpload(HttpServletRequest request,MultipartFile fileUpload) throws IOException {
String path = request.getSession().getServletContext().getRealPath("/upload"); //获取当前路径
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
System.out.println(fileUpload.getOriginalFilename()); //上传文件名
fileUpload.transferTo(new File(path,fileUpload.getOriginalFilename()));
System.out.println(path);
return "success";
}
<form action="user/fileUpload" method="post" enctype="multipart/form-data">
<input type="file" name="fileUpload"> <br><%--此处的id值,需要与对应的处理 MultipartFile 实例参数名一致--%>
<input type="submit" value="上传">
</form>
springmvc异常处理
用户自定义异常类,需要继承Exception
public class SysException extends Exception {
private String message;
public SysException(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
异常处理类 实现 HandlerExceptionResolver 接口 ,判定捕获的异常是否为自己定义的异常,并且设定消息,返回到指定视图
**
* 异常处理器
*/
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常逻辑
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
SysException sysException = null;
if(ex instanceof SysException){
sysException = (SysException)ex;
}else {
sysException = new SysException("未知异常。。。");
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("errorMsg",sysException.getMessage());
modelAndView.setViewName("error"); //返回到指定页面,显示异常信息
return modelAndView;
}
}
捕获异常,并抛出
@RequestMapping(value = "/select")
public String userSelect() throws SysException {
try {
int i = 1/0;
}catch (Exception e){
throw new SysException("分母为zero");
}
return "success";
}
拦截器的使用
配置拦截器,如果存在多个拦截器,可配置多个 <mvc:interceptor>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/*"/> <!--被拦截的请求-->
<!-- <mvc:exclude-mapping path=""/>--> <!--不被拦截的请求-->
<bean class="com.zxit.interceptors.UserInterceptors"/> <!-- 拦截器处理-->
</mvc:interceptor>
</mvc:interceptors>
package com.zxit.interceptors;
public class UserInterceptors implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器前置"); //可以在此处request,response
return true; //true 为放行,fase 为不放行
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器后置");//可以在此处request,response
}
}