springMVC
SpringMVC分为:
前端控制器:当用户请求时综合调用映射器、适配器、控制器、视图解析器对用户的请求进行响应
映射器:对前端控制器发送的URL路径进行检查,如果路径错误返回404
适配器:寻找正确的控制器,如果找不到抛出异常
控制器:对用户的请求进行处理,将请求得到的数据以及要显示的视图放入ModelAndView对象中
视图解析器:接收ModelAndView对象,从中获取数据,经过处理组合成视图交给前端控制器进行处理
DispatcherServlet原理
1、根据请求的路径找到HandlerMethod(带有Method反射属性,也就是对应Controller中的方法)
2、然后匹配路径对应的拦截器
3、通过HandlerMapping接口实现类获得HandlerExecutionChain对象(包含HandlerMethod和拦截器)
4、有了HandlerExecutionChain之后,通过HandlerAdapter对象进行处理得到ModelAndView对象
调用HandlerMethod内部handle的时候:
1、使用各种HandlerMethodArgumentResolver接口实现类,完成参数绑定
2、使用到各种Converter接口实现类,完成类型转换
3、使用各种HandlerMethodReturnValueHandler接口实现类,处理返回值
4、最终返回值被处理成ModelAndView对象
5、这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理
5、RequestToViewNameTranslator接口实现类将请求地址解析为视图名(若有手动设置视图名,则使用手动设置的)
6、通过各种View和ViewResolver接口实现类渲染视图(将Model中的数据放到request域对象中,页面的编译。。。)
前端控制器
前端控制器在web.xml中配置
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springMVC.xml
1
springmvc
/
两种映射器
text
text
两种适配器
控制器
后端控制器代码
public class MyController implements org.springframework.web.servlet.mvc.Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
String username = req.getParameter("username");
String password = req.getParameter("password");
// req.setAttribute("username", username);
// req.setAttribute("password", password);
ModelAndView view = new ModelAndView();
if("lisi".equals(username)&&"123".equals(password)){
view.setViewName("Hello.jsp");
}
else{
view.setViewName("login.jsp");
}
return view;
}
}
视图解析器
视图解析器的配置前缀后缀
使用注解的方式配置springMVC
注意:注解适配器和映射器要一起使用才有效
注解适配器和映射器要一起使用才有效
- @RequestMapping("path"):在方法上使用该注解,配置对应的映射路径
@Controller
public class TextControler{
@RequestMapping("show1")
public ModelAndView show1(){}
}
springMVC后端控制器进行响应的三种方式
ModleAndView类型返回值:
view.setViewName("Hello"); 保存要显示的视图
view.addObject("password", password); 向域对象中保存数据(实际是保存到request域对象中)
@RequestMapping("show1")
public ModelAndView show1(HttpServletRequest req){
String username = req.getParameter("username");
String password = req.getParameter("password");
ModelAndView view = new ModelAndView();
view.addObject("username", username);
view.addObject("password", password);
view.setViewName("Hello");
return view;
}
@RequestMapping("show1")
public ModelAndView show1(HttpServletRequest req){
String username = req.getParameter("username");
String password = req.getParameter("password");
ModelAndView view = new ModelAndView();
view.addObject("username", username);
view.addObject("password", password);
view.setViewName("Hello");
return view;
}
- String类型返回值返回视图位置,使用Modle以及ModleMap来保存数据
@RequestMapping("show2")
public String show2(Model model,HttpServletRequest req){
String username = req.getParameter("username");
String password = req.getParameter("password");
model.addAttribute("username", username);
model.addAttribute("password", password);
return "Hello";
}
void类型返回值要用域对象来保存数据,通过请求转发和重定向来进行响应
@RequestMapping("show3")
public void show3(HttpServletRequest req,HttpServletResponse resp){
String username = req.getParameter("username");
String password = req.getParameter("password");
req.setAttribute("username", username);
req.setAttribute("password", password);
try {
req.getRequestDispatcher("Hello.jsp").forward(req, resp);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
参数绑定
简单参数绑定:传入的数据是以key/value的形式进行传递,key和后端控制器的形参名字相同,可以使用注解@RequestParam("username")为后端控制器的形参名起别名,与key相对应
Pojo参数绑定:传入的数据是以key/value的形式进行传递,key值与Pojo中的属性名称相同
自定义类型: 进行date和数据类型的绑定,需要自己编写转换类
自定义转换类型配置步骤:
- 编写转换类
public class DateConvert implements Converter{
@Override
public Date convert(String source) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
return format.parse(source);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
- 在spring配置文件中进行配置
- 在实体类中对绑定的Date属性值进行绑定
private String username;
private String password;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
- 配置后端控制器
@RequestMapping("show4")
public String show4(Model model,User user){
model.addAttribute("user", user);
return "Hello";
}
参数绑定数组(数组和list集合一样)
前端页面
实体类
private String username;
private String password;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
private List add;
控制器:
@RequestMapping("show5")
public String show5(String[] hobby){
}
全局异常处理
- 1、自定义异常类(继承Exception或RuntimeException)
public class CustomException extends Exception{
private String msg;
public CustomException(String msg) {
super(msg);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
- 2、自定义异常处理器实现 HandlerExceptionResolver接口
public class ExceptionHandler implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object object,
Exception ex) {
CustomException customException=null;
if (ex instanceof CustomException) {
customException=(CustomException)ex;
}else{
customException=new CustomException("未知错误");
}
ModelAndView view = new ModelAndView();
view.addObject("error", customException);
view.setViewName("error");
return view;
}
}
- 3、在springmvc配置文件中配置全局异常控制器
静态资源的释放
在配置文件中进行配置
文件上传
1、编写配置文件
2、上传单个文件,后端控制器:
public String upload(MultipartFile file,HttpServletRequest req) throws IllegalStateException, IOException{
if(file==null){
return "uploadFile";
}
//取出文件名
String filename = file.getOriginalFilename();
//根据文件的虚拟入境找到真实入境
String path = req.getServletContext().getRealPath("/temp");
File file2 = new File(path);
if (!file2.exists()) {
//创建目录
file2.mkdirs();
}
//将传入的文件按照真实入境和文件名写出来
file.transferTo(new File(file2,filename));
return "success";
}
3、批量上传文件,后端控制器
@RequestMapping("/upload1")
public String upload1(MultipartFile[] file,HttpServletRequest req) throws IllegalStateException, IOException{
for (MultipartFile multipartFile : file) {
if(file==null){
return "uploadFile";
}
String filename = multipartFile.getOriginalFilename();
String realPath = req.getServletContext().getRealPath("/team");
File file2 = new File(realPath);
if (!file2.exists()) {
file2.mkdirs();
}
multipartFile.transferTo(new File(file2,filename));
}
return "success";
}
4、编写前端表单页面
注意:
把form表单的默认的enctype 类型改成 enctype="multipart/form-data"
表单的提交方式设为:post