org.springframework
spring-webmvc
4.3.2.RELEASE
javax.servlet
servlet-api
2.5
provided
Archetype Created Web Application
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
springmvc
/
package com.bobo.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UserController implements Controller {
/**
* 具体处理请求的方法
* @param httpServletRequest
* @param httpServletResponse
* @return
* @throws Exception
*/
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception {
System.out.println("请求进来了...");
ModelAndView mm = new ModelAndView();
mm.setViewName("/index.jsp");
return mm;
}
}
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
8082
/
utf-8
package com.bobo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.jws.WebParam;
@Controller // 将当前类的对象交给容器管理
@RequestMapping("/user") // 配置的而是请求的路径
public class UserController {
/**
* 查询方法
* 请求地址
* http://localhost:8082/user/query
* @return
*/
@RequestMapping("/query")
public ModelAndView query(){
System.out.println("query");
ModelAndView mm = new ModelAndView();
mm.setViewName("/index.jsp");
return mm;
}
/**
* 添加方法
* 请求地址
* http://localhost:8082/user/addUser
* @return
*/
@RequestMapping("/addUser")
public ModelAndView addUser(){
System.out.println("add User ...");
ModelAndView mm = new ModelAndView();
mm.setViewName("/index.jsp");
return mm;
}
}
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServletcontext.
# Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
/**
* 查询方法
* 请求地址
* http://localhost:8082/user/query
* @return
*/
@RequestMapping("/query")
public ModelAndView query(){
System.out.println("query");
ModelAndView mm = new ModelAndView();
mm.setViewName("/index.jsp");
return mm;
}
@RequestMapping("/update")
public void updateUser(){
System.out.println("update .... ");
}
/**
* 返回结果信息为空
* void + @ResponseBody
*/
@RequestMapping("/update")
@ResponseBody
public void updateUser(){
System.out.println("update .... ");
}
**
* 要跳转到哪个页面我们直接返回该页面对应的字符串即可
*
* @return
*/
@RequestMapping("/deleteUser")
public String deleteUser(){
System.out.println("delete .....");
// "/index.jsp"中的 "/" 表示的是绝对路径
return "redirect:/index.jsp";
}
/**
* 要跳转到哪个页面我们直接返回该页面对应的字符串即可
*
* @return
*/
@RequestMapping("/deleteUser1")
public String deleteUser1(){
System.out.println("delete1 .....");
// "/index.jsp"中的 "/" 表示的是绝对路径
return "index";
}
@RequestMapping("/deleteUser")
public String deleteUser(){
System.out.println("delete .....");
// "/index.jsp"中的 "/" 表示的是绝对路径
return "redirect:/index.jsp";
}
@RequestMapping("/queryAll")
public void queryAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("query All ... ");
request.getRequestDispatcher("/index.jsp").forward(request,response);
//response.sendRedirect("/index.jsp");
}
/**
* 接收的参数为简单数据类型
* @param userName
* @param age
* @return
*/
@RequestMapping("/query1")
public String query1(String userName, Integer age){
System.out.println("query1 ....."+ userName + " " + age);
return "/index.jsp";
}
/**
* 接收的参数为简单数据类型
* @param userName
* @param age
* @return
*/
@RequestMapping("/query1")
public String query1(@RequestParam(value = "name",defaultValue = "lisi") String userName,
@RequestParam(value = "userAge",defaultValue = "18") Integer age){
System.out.println("query1 ....."+ userName + " " + age);
return "/index.jsp";
}
package com.bobo.bean;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
public class StudentBean {
private Integer id;
private String userName;
private Integer age;
private String address;
private List favrites;
public List getFavrites() {
return favrites;
}
public void setFavrites(List favrites) {
this.favrites = favrites;
}
// 包装类
private Book book;
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "StudentBean{" +
"id=" + id +
", userName='" + userName + '\'' +
", age=" + age +
", address='" + address + '\'' +
", book=" + book +
'}';
}
}
/**
* 通过自定义对象来接收参数
* @param stu
* @return
*/
@RequestMapping("/addStudent")
public String addStudent(StudentBean stu){
System.out.println(stu);
return "/index.jsp";
}
package com.bobo.bean;
public class Book {
private Integer bookId;
private String bookName;
private String author;
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
", author='" + author + '\'' +
'}';
}
}
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/29
Time: 16:36
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
学生管理
@RequestMapping("/addStudentNew")
public String addStudentNew(String userName,String[] favrites){
System.out.println(userName + ":" + Arrays.toString(favrites) );
return "/index.jsp";
}
@RequestMapping("/addStudentList")
public String addStudentList(String userName, List favrites){
System.out.println(userName + ":" + favrites );
return "/index.jsp";
}
package com.bobo.convert;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 自定义一个转换器
* 实现 String到Date类型的转换
*/
public class DateConvert implements Converter {
@Override
public Date convert(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
Archetype Created Web Application
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
springmvc
/
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
true
forceResponseEncoding
true
encodingFilter
/*
@RequestMapping("/fun1")
public ModelAndView fun1(){
System.out.println("fun1...");
ModelAndView mm = new ModelAndView();
mm.setViewName("/person1.jsp");
// 绑定一个回传信息
mm.addObject("msg","Hello World");
return mm;
}
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/29
Time: 17:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
Person管理
${ msg }
/**
* 响应数据我们可以在形参中声明一个Map集合
* 来保存要响应的数据
* @return
*/
@RequestMapping("/fun2")
public String fun2(Map map){
map.put("msg","map类型数据");
map.put("username","张三");
System.out.println("fun2....");
return "/person2.jsp";
}
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/29
Time: 17:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
Person管理
${ requestScope.msg }
${ sessionScope.msg }
${ applicationScope.msg }
${ username }
@RequestMapping("/fun3")
public String fun3(Model model){
model.addAttribute("msg","msg-->model");
model.addAttribute("username","bobo");
System.out.println("fun3....");
return "/person2.jsp";
}
@RequestMapping("/fun4")
public String fun4(ModelMap model){
model.addAttribute("msg","msg-->modelMap你好啊");
model.addAttribute("username","bobo");
System.out.println("fun4....");
return "/person2.jsp";
}
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/29
Time: 17:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
Person管理
${ requestScope.msg }
${ sessionScope.msg }
${ applicationScope.msg }
${ username }
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String encoding = this.getEncoding();
if (encoding != null) {
if (this.isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
if (this.isForceResponseEncoding()) {
response.setCharacterEncoding(encoding);
}
}
filterChain.doFilter(request, response);
}
Archetype Created Web Application
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
springmvc
/
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
true
forceResponseEncoding
true
encodingFilter
/*
commons-fileupload
commons-fileupload
1.3.1
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/29
Time: 20:03
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
文件上传:
package com.bobo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 文件上传操作
* @return
*/
@RequestMapping("/fileUpload")
public String fileUpload(String username, MultipartFile headFile) throws IOException {
System.out.println(username+" : " + headFile.getOriginalFilename() );
headFile.transferTo(new File("d:/tools/","123.jpg"));
return "/index.jsp";
}
}
/**
* 文件下载
*/
@RequestMapping("/download")
public void fileDownload(HttpServletRequest request, HttpServletResponse response) throws Exception {
File file = new File("d:/tools/","123.jpg");
// 设置响应头信息
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + file.getName());
// 打开需要下载的文件
InputStream in = new FileInputStream(file);
// 激活下载的操作
ServletOutputStream outputStream = response.getOutputStream();
// 实现下载操作--> 本质就是一个文件的复制操作
byte[] b = new byte[1024*1024];
int length= 0;
while((length = in.read(b)) > 0){
outputStream.write(b,0,length);
}
// 关闭连接
outputStream.close();
in.close();
}
/**
* 使用SpringMVC中提供的下载方式
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/download2")
public ResponseEntity download2(HttpServletRequest request) throws Exception{
File file = new File("d:/tools/","123.jpg");
byte[] body = null;
InputStream in = new FileInputStream(file);
body = new byte[in.available()];
in.read(body);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition","attachment;fileName=" + file.getName());
HttpStatus status = HttpStatus.OK;
ResponseEntity entity = new ResponseEntity<>(body,headers,status);
return entity;
}
default
*.html
default
*.css
default
*.js
default
*.jpg
default
*.png
org.hibernate
hibernate-validator
5.3.0.Alpha1
package com.bobo.controller;
import com.bobo.bean.UserBean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
/**
*
* @param user @Validated 修饰表示user会被校验
* @param br 校验的结果
* @return
*/
@RequestMapping("/addUser")
public String addUser(@Validated UserBean user, BindingResult br, Model m) {
// 对客户端提交的用户数据检验
/*if(user != null){
if(user.getUserName().length() > 3 ){
}
}*/
// 获取校验结果
List allErrors = br.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getDefaultMessage());
}
m.addAttribute("errors",allErrors);
return "/index.jsp";
}
}
package com.bobo.controller;
import com.bobo.bean.UserBean;
import com.bobo.group.GroupInterface1;
import com.bobo.group.GroupInterface2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
/**
*
* @param user @Validated 修饰表示user会被校验
* @param br 校验的结果
* @return
*/
@RequestMapping("/addUser")
public String addUser(@Validated(value = GroupInterface2.class) UserBean user, BindingResult br, Model m) {
// 对客户端提交的用户数据检验
/*if(user != null){
if(user.getUserName().length() > 3 ){
}
}*/
// 获取校验结果
List allErrors = br.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getDefaultMessage());
}
m.addAttribute("errors",allErrors);
return "/index.jsp";
}
@RequestMapping("/udpateUser")
public String udpate(@Validated(value = GroupInterface1.class) UserBean user, BindingResult br, Model m){
return "/index.jsp";
}
}
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/doLogin")
public String doLogin(String userName, String password, Model model){
model.addAttribute("userName",userName);
model.addAttribute("password",password);
return "forward:/login.jsp";
}
}
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/30
Time: 14:14
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登录页面
获取全局配置信息:${as}
/**
* 如果我们用对象去接收请求传递的参数。
* 那么该对象默认会被保存到Model对象中
* model.addAttribute("userBean",user)
* @param user
* @return
*/
@RequestMapping("/addUser")
public String addUser(UserBean user) {
System.out.println(user);
return "/user.jsp";
}
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/1/29
Time: 20:03
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
获取全局配置信息:${as}
/**
* 配置全局的信息
* 该类中的其他方法在处理请求后都会绑定本方法的返回信息
* @return
*/
@ModelAttribute("as")
public List getAllAddress(){
return Arrays.asList("深圳","长沙","北京");
}
package com.bobo.resolver;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 全局异常处理器
*/
@Component
public class MyExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest
, HttpServletResponse httpServletResponse, Object o, Exception e) {
System.out.println(e.getMessage());
ModelAndView mm = new ModelAndView();
mm.setViewName("/500.jsp");
return mm;
}
}
com.fasterxml.jackson.core
jackson-core
2.5.2
com.fasterxml.jackson.core
jackson-databind
2.5.2
@Controller
@RequestMapping("/person")
public class PersonController {
@RequestMapping("/getUser")
@ResponseBody
public UserBean getUser(){
UserBean user = new UserBean();
user.setId(666);
user.setUserName("波波");
user.setGender("男");
user.setAddress("湖南长沙");
return user;
}
}
@RequestMapping("/getAllUser")
@ResponseBody
public List getAllUser(){
UserBean user = new UserBean();
user.setId(666);
user.setUserName("波波");
user.setGender("男");
user.setAddress("湖南长沙");
UserBean user2 = new UserBean();
user2.setId(123);
user2.setUserName("波波1");
user2.setGender("男1");
user2.setAddress("湖南长沙1");
List list = new ArrayList<>();
list.add(user);
list.add(user2);
return list;
}
通过以上案例可知,我们返回的任意的Java对象数据Jackson都会将其转换为JSON数据。
/**
* 客户端发送的是JSON格式的字符串
* @param user
*/
@RequestMapping("/addUser2")
@ResponseBody
public void addUser2(@RequestBody UserBean user){
System.out.println(user);
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
String value() default "";
}
package com.bobo.controller;
import com.bobo.bean.UserBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* Restful风格编程介绍
*/
/*@ResponseBody
@Controller*/
@RestController
public class StudentController {
/**
* 查询用户的方法
* 基于Restf风格的规范,该请求只能接受GET方式提交的请求
* @return
*/
//@RequestMapping("/getAll")
@GetMapping("/stus/{id}")
//@RequestMapping(value = "/stus",method = RequestMethod.POST)
public List getAllUser(@PathVariable Integer id){
System.out.println("查询数据--->"+id);
List list = new ArrayList<>();
list.add(new UserBean(1,"root","123456"));
list.add(new UserBean(2,"admin","123456"));
return list;
}
/**
* 添加用户数据
* 接受POST方式提交
* @param user
* @return
*/
@PostMapping("/stus")
public String addUser(@RequestBody UserBean user){
System.out.println("添加数据"+user);
return "数据添加成功...";
}
@DeleteMapping("/stus/{id}")
public String deleteUser(@PathVariable Integer id){
System.out.println("删除的编号:" + id);
return "删除数据成功...";
}
@PutMapping("/stus")
public String updateUser(@RequestBody UserBean user){
System.out.println("更新数据:" + user);
return "更新数据成功...";
}
}
package com.bobo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义的拦截器
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* 自定义处理器处理请求之前执行的方法
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* true 表示放过请求
* false 表示拦截请求
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest
, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle .... ");
return true;
}
/**
* 在目标方法执行完成后执行的方法
* postHandle 在afterCompletion之前执行
* 返回ModelAndView之前执行
* 我们可以修改ModelAndView中的信息
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest
, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
System.out.println("ModelAndView执行之前操作...");
modelAndView.setViewName("/index.jsp");
System.out.println("postHandle ....");
}
/**
* 在目标方法执行完成后执行的方法
* 返回ModelAndView之后执行
* 改变不了ModelAndView中的信息
* 只能做一些资源回收相关的工作
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest
, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion ... ");
}
}
org.springframework
spring-webmvc
4.3.4.RELEASE
javax.servlet
servlet-api
2.5
provided
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
8082
/
utf-8
Archetype Created Web Application
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
springmvc
/
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
true
forceResponseEncoding
true
encodingFilter
/*
default
*.html
default
*.css
default
*.js
default
*.jpg
default
*.png
package com.bobo.bean;
public class UserBean {
private Integer id;
private String userName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "UserBean{" +
"id=" + id +
", userName='" + userName + '\'' +
'}';
}
public UserBean(Integer id, String userName) {
this.id = id;
this.userName = userName;
}
public UserBean() {
}
}
package com.bobo.dao;
import com.bobo.bean.UserBean;
public interface IUserDao {
UserBean getUserBean();
}
package com.bobo.dao.impl;
import com.bobo.bean.UserBean;
import com.bobo.dao.IUserDao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements IUserDao {
@Override
public UserBean getUserBean() {
return new UserBean(666,"bobo");
}
}
package com.bobo.service;
import com.bobo.bean.UserBean;
public interface IUserService {
UserBean getUserBean();
}
package com.bobo.service.impl;
import com.bobo.bean.UserBean;
import com.bobo.dao.IUserDao;
import com.bobo.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private IUserDao dao;
@Override
public UserBean getUserBean() {
return dao.getUserBean();
}
}
package com.bobo.controller;
import com.bobo.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private IUserService service;
@GetMapping("/user/query")
public String query(){
return service.getUserBean().toString();
}
}
package com.bobo.test;
import com.bobo.bean.UserBean;
import com.bobo.service.IUserService;
import com.bobo.service.impl.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
@Test
public void fun1(){
// 进入源码 Ctrl+鼠标点击 进入
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(ac.getBean(IUserService.class));
}
}
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh,ApplicationContext parent) throws BeansException {
// 初始化父类
super(parent);
// 设置本地配置信息
this.setConfigLocations(configLocations);
// 完成Spring容器的初始化操作
if (refresh) {
this.refresh();
}
}
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 准备工作
this.prepareRefresh();
// 获取BeanFactory工厂对象,并且完成 配置文件的而加重解析操作
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context
initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新BeanFactory对象
this.refreshBeanFactory();
// 获取BeanFactory对象 说明已经完成了 BeanFactory的创建和 配置文件的加载解析操作
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " +
beanFactory);
}
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
// 判断BeanFactory是否已经存在
if (this.hasBeanFactory()) {
// 存在 就销毁和关闭
this.destroyBeans();
this.closeBeanFactory();
}
try {
// 创建BeanFactory对象
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
// 加载解析配置文件
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(this.getInternalParentBeanFactory());
}
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
// 核心代码 直接进入
this.loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
Resource[] var3 = resources;
int var4 = resources.length;
for(int var5 = 0; var5 < var4; ++var5) {
Resource resource = var3[var5];
counter += this.loadBeanDefinitions((Resource)resource);
}
// 统计解析的配置文件的个数
return counter;
}
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return this.loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (this.logger.isInfoEnabled()) {
this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!((Set)currentResources).add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
} else {
int var5;
try {
// 获取配置文件对应的字节输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
// 设置对应的编码方式
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 核心代码 执行解析操作
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
inputStream.close();
}
} catch (IOException var15) {
throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
} finally {
((Set)currentResources).remove(encodedResource);
if (((Set)currentResources).isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
return var5;
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {
try {
// 将xml中的内容加载到Document对象中
Document doc = this.doLoadDocument(inputSource, resource);
// 完成配置文件的注册操作 将配置文件中的信息载入到BeanDefinition对象中
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var4) {
throw var4;
} catch (SAXParseException var5) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),"Line " + var5.getLineNumber() + " in XML document from " + resource + " isinvalid", var5);
} catch (SAXException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),"XML document from " + resource + " is invalid", var6);
} catch (ParserConfigurationException var7) {
throw new BeanDefinitionStoreException(resource.getDescription(),"Parser configuration exception parsing XML from " + resource, var7);
} catch (IOException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(),"IOException parsing XML document from " + resource, var8);
} catch (Throwable var9) {
throw new BeanDefinitionStoreException(resource.getDescription(),"Unexpected exception parsing XML document from " + resource, var9);
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
int countBefore = this.getRegistry().getBeanDefinitionCount();
// 具体注册的方法
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
// 获取Document对象的root标签
Element root = doc.getDocumentElement();
// 具体操作的方法
this.doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
// 对profile标签处理
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute("profile");
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
}
return;
}
}
}
// 解析配置文件之前的操作
this.preProcessXml(root);
// 解析配置文件
this.parseBeanDefinitions(root, this.delegate);
// 解析配置文件之后的操作
this.postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
// 获取根节点下的所有的直接子标签
NodeList nl = root.getChildNodes();
// 循环获取每一个子标签
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)node;
if (delegate.isDefaultNamespace(ele)) {
// 解析默认的标签
this.parseDefaultElement(ele, delegate);
} else {
// 解析自定义的标签
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 配置文件的解析
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册我们获取的 BeanDefinitionHolder 对象
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,
this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition
with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(newBeanComponentDefinition(bdHolder));
}
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele,BeanDefinition containingBean) {
// 获取bean标签的id属性
String id = ele.getAttribute("id");
// 获取bean标签的name属性
String nameAttr = ele.getAttribute("name");
List aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",;");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if (this.logger.isDebugEnabled()) {
this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
// 检查name是否唯一
this.checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition,
this.readerContext.getRegistry(), true);
} else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName,
aliasesArray);
} else {
return null;
}
}
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
// 关键代码
registry.registerBeanDefinition(beanName,
definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
}
@Override
public void refresh() throws BeansException, IllegalStateException {
//startupShutdownMonitor对象在spring环境刷新和销毁的时候都会用到,确保刷新和销毁不会同时执行
synchronized (this.startupShutdownMonitor) {
// 准备工作,例如记录事件,设置标志,检查环境变量等,并有留给子类扩展的位置,用来将属性加入到applicationContext中
prepareRefresh();
// 创建beanFactory,这个对象作为applicationContext的成员变量,可以被applicationContext拿来用,
// 并且解析资源(例如xml文件),取得bean的定义,放在beanFactory中
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 对beanFactory做一些设置,例如类加载器、SPEL解析器、指定bean的某些类型的成员变量对应某些对象.
prepareBeanFactory(beanFactory);
try {
// 子类扩展用,可以设置bean的后置处理器(bean在实例化之后这些后置处理器会执行)
postProcessBeanFactory(beanFactory);
// 执行beanFactory后置处理器(有别于bean后置处理器处理bean实例,beanFactory 后置处理器处理bean定义)
invokeBeanFactoryPostProcessors(beanFactory);
// 将所有的bean的后置处理器排好序,但不会马上用,bean实例化之后会用到
registerBeanPostProcessors(beanFactory);
// 初始化国际化服务
initMessageSource();
// 创建事件广播器
initApplicationEventMulticaster();
// 空方法,留给子类自己实现的,在实例化bean之前做一些ApplicationContext相关的操作
onRefresh();
// 注册一部分特殊的事件监听器,剩下的只是准备好名字,留待bean实例化完成后再注册
registerListeners();
// 单例模式的bean的实例化、成员变量注入、初始化等工作都在此完成
finishBeanFactoryInitialization(beanFactory);
// applicationContext刷新完成后的处理,例如生命周期监听器的回调,广播通知等
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization -
cancelling refresh attempt", ex);
// 刷新失败后的处理,主要是将一些保存环境信息的集合做清理
destroyBeans();
// applicationContext是否已经激活的标志,设置为false
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
public final void init() throws ServletException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Initializing servlet '" + this.getServletName() +"'");
}
try {
PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(),this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader,this.getEnvironment()));
this.initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
} catch (BeansException var4) {
this.logger.error("Failed to set bean properties on servlet '" +
this.getServletName() + "'", var4);
throw var4;
}
// 关键代码
this.initServletBean();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Servlet '" + this.getServletName() + "' configured successfully");
}
}
protected final void initServletBean() throws ServletException {
this.getServletContext().log("Initializing Spring FrameworkServlet '" + this.getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();
try {
// 初始化 Web容器
this.webApplicationContext = this.initWebApplicationContext();
// 预留给我们扩展的方法
this.initFrameworkServlet();
} catch (ServletException var5) {
this.logger.error("Context initialization failed", var5);
throw var5;
} catch (RuntimeException var6) {
this.logger.error("Context initialization failed", var6);
throw var6;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization completed in " + elapsedTime + " ms");
}
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
// 如果找到了 rootContext
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac =(ConfigurableWebApplicationContext)wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
// 查找容器
wac = this.findWebApplicationContext();
}
if (wac == null) {
// 创建容器
wac = this.createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
// 刷新容器
this.onRefresh(wac);
}
if (this.publishContext) {
String attrName = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName, wac);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Published WebApplicationContext of servlet '"+ this.getServletName() + "' as ServletContext attribute with name [" + attrName+ "]");
}
}
return wac;
}
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class> contextClass = this.getContextClass();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Servlet with name '" + this.getServletName() + "'will try to create custom WebApplicationContext context of class '" + contextClass.getName() + "', using parent context [" + parent + "]");
}
if(!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Fatal initialization error in servlet with name '" + this.getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
} else {
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(this.getEnvironment());
wac.setParent(parent);
wac.setConfigLocation(this.getContextConfigLocation());
// 核心代码
this.configureAndRefreshWebApplicationContext(wac);
return wac;
}
}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac){
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
if (this.contextId != null) {
wac.setId(this.contextId);
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(this.getServletContext().getContextPath()) + '/' + this.getServletName());
}
}
wac.setServletContext(this.getServletContext());
wac.setServletConfig(this.getServletConfig());
wac.setNamespace(this.getNamespace());
wac.addApplicationListener(new SourceFilteringListener(wac, new
FrameworkServlet.ContextRefreshListener()));
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(this.getServletContext(), this.getServletConfig());
}
this.postProcessWebApplicationContext(wac);
this.applyInitializers(wac);
// 关键代码 完成SpringMVC配置文件的加载解析操作 Spring容器初始化操作
wac.refresh();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (HttpMethod.PATCH != httpMethod && httpMethod != null) {
super.service(request, response);
} else {
// 具体处理请求的方法
this.processRequest(request, response);
}
}
protected final void processRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = this.buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
this.initContextHolders(request, localeContext, requestAttributes);
try {
this.doService(request, response);
} catch (ServletException var17) {
failureCause = var17;
throw var17;
} catch (IOException var18) {
failureCause = var18;
throw var18;
} catch (Throwable var19) {
failureCause = var19;
throw new NestedServletException("Request processing failed",var19);
} finally {
this.resetContextHolders(request, previousLocaleContext,
previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
if (this.logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request",(Throwable)failureCause);
} else if (asyncManager.isConcurrentHandlingStarted()) {
this.logger.debug("Leaving response open for concurrent processing");
} else {
this.logger.debug("Successfully completed request");
}
}
this.publishRequestHandledEvent(request, response, startTime,(Throwable)failureCause);
}
}
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (this.logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
Map attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration attrNames = request.getAttributeNames();
label108:
while(true) {
String attrName;
do {
if (!attrNames.hasMoreElements()) {
break label108;
}
attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude &&
!attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot.put(attrName,
request.getAttribute(attrName));
}
}
// 将Web容器保存到了 Request请求中
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE,Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
// 处理请求分发
this.doDispatch(request, response);
} finally {
if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() &&
attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
// 检查是否有文件上传
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request,mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" +getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request,response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest,response)) {
return;
}
mv = ha.handle(processedRequest, response,mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response,mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
this.processDispatchResult(processedRequest, response,mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response,
mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response,mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
this.logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, this typically results from an additional MultipartFilter in web.xml");
} else {
if (!(request.getAttribute("javax.servlet.error.exception")instanceof MultipartException)) {
// 文件上传操作的具体执行
return this.multipartResolver.resolveMultipart(request);
}
this.logger.debug("Multipart resolution failed for current request before - skipping re-resolution for undisturbed error rendering");
}
}
return request;
}
public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {
Assert.notNull(request, "Request must not be null");
// 是否需要延迟 处理
if (this.resolveLazily) {
return new DefaultMultipartHttpServletRequest(request) {
protected void initializeMultipart() {
MultipartParsingResult parsingResult = CommonsMultipartResolver.this.parseRequest(request);
this.setMultipartFiles(parsingResult.getMultipartFiles());
this.setMultipartParameters(parsingResult.getMultipartParameters());
this.setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes());
}
};
} else {
// 解析请求
MultipartParsingResult parsingResult = this.parseRequest(request);
return new DefaultMultipartHttpServletRequest(request,parsingResult.getMultipartFiles(), parsingResult.getMultipartParameters(),
parsingResult.getMultipartParameterContentTypes());
}
}
protected MultipartParsingResult parseRequest(HttpServletRequest request)throws MultipartException {
String encoding = this.determineEncoding(request);
FileUpload fileUpload = this.prepareFileUpload(encoding);
try {
// 获取提交的表单中的所有的表单域
List fileItems = ((ServletFileUpload)fileUpload).parseRequest(request);
// 解析每一个表单域
return this.parseFileItems(fileItems, encoding);
} catch (SizeLimitExceededException var5) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(),var5);
} catch (FileSizeLimitExceededException var6) {
throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), var6);
} catch (FileUploadException var7) {
throw new MultipartException("Failed to parse multipart servlet request", var7);
}
}
protected CommonsFileUploadSupport.MultipartParsingResult parseFileItems(List fileItems, String encoding) {
MultiValueMap multipartFiles = new LinkedMultiValueMap();
Map multipartParameters = new HashMap();
Map multipartParameterContentTypes = new HashMap();
Iterator var6 = fileItems.iterator();
while(true) {
while(var6.hasNext()) {
FileItem fileItem = (FileItem)var6.next();
// 普通表单域处理
if (fileItem.isFormField()) {
String partEncoding = this.determineEncoding(fileItem.getContentType(), encoding);
String value;
if (partEncoding != null) {
try {
// 获取对应的编码方式
value = fileItem.getString(partEncoding);
} catch (UnsupportedEncodingException var12) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Could not decode multipartitem '" + fileItem.getFieldName() + "' with encoding '" + partEncoding + "': using platform default");
}
value = fileItem.getString();
}
} else {
// 得到提交的值
value = fileItem.getString();
}
String[] curParam = (String[])multipartParameters.get(fileItem.getFieldName());
if (curParam == null) {
// 将提交的数据保存起来
multipartParameters.put(fileItem.getFieldName(), new String[]{value});
} else {
String[] newParam = StringUtils.addStringToArray(curParam, value);
multipartParameters.put(fileItem.getFieldName(),newParam);
}
multipartParameterContentTypes.put(fileItem.getFieldName(), fileItem.getContentType());
} else {
// 表单提交的文件信息
CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
// 将表单提交的文件信息 封装到了 CommonsMultipartFile 对象中
multipartFiles.add(file.getName(), file);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize() + " bytes with original filename [" + file.getOriginalFilename() + "], stored " + file.getStorageDescription());
}
}
}
return new CommonsFileUploadSupport.MultipartParsingResult(multipartFiles, multipartParameters, multipartParameterContentTypes);
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
// 检查是否有文件上传
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 处理器映射器
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
// 获取处理器适配器
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request,mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest,response)) {
return;
}
// 处理适配器处理请求
mv = ha.handle(processedRequest, response,mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response,mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handlerdispatch failed", var21);
}
this.processDispatchResult(processedRequest, response,mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller)handler).handleRequest(request, response);
}
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
public void contextInitialized(ServletContextEvent event) {
// 初始化web容器
this.initWebApplicationContext(event.getServletContext());
}
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!");
} else {
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
try {
if (this.context == null) {
// 创建容器对象
this.context = this.createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
ApplicationContext parent = this.loadParentContext(servletContext);
cwac.setParent(parent);
}
// 完全Spring IoC容器的初始化操作
this.configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
// 将Spring的IoC容器对象保存在了Servlet容器中 key是
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}
return this.context;
} catch (RuntimeException var8) {
logger.error("Context initialization failed", var8);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
throw var8;
} catch (Error var9) {
logger.error("Context initialization failed", var9);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9);
throw var9;
}
}
protected WebApplicationContext initWebApplicationContext() {
// 获取Spring IoC容器对象
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
wac = this.findWebApplicationContext();
}
if (wac == null) {
wac = this.createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
this.onRefresh(wac);
}
if (this.publishContext) {
String attrName = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName, wac);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Published WebApplicationContext of servlet '" + this.getServletName() + "' as ServletContext attribute with name [" + attrName + "]");
}
}
return wac;
}
public static WebApplicationContext getWebApplicationContext(ServletContext sc){
return getWebApplicationContext(sc,WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class> contextClass = this.getContextClass();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Servlet with name '" + this.getServletName() + "'will try to create custom WebApplicationContext context of class '" +contextClass.getName() + "', using parent context [" + parent + "]");
}
if(!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Fatal initialization error in servlet with name '" + this.getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
} else {
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(this.getEnvironment());
// Spring MVC的IoC容器对象设置Spring 的IoC容器对象为父容器
wac.setParent(parent);
wac.setConfigLocation(this.getContextConfigLocation());
this.configureAndRefreshWebApplicationContext(wac);
return wac;
}
}