1、传统的javaweb,前端请求直接发送到servlet,在springmvc中设置了一个前端控制器Dispatcherservlet(本质也是servlet),前端控制器会转发请求到对应的controller中(某个指定业务模块的servlet)
2、例子
java
package com.example.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class WebInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(MymvcConfig.class);//该类配置了需要扫描哪些包下的bean交给spring管理
servletContext.addFilter("encodingFilter", new CharacterEncodingFilter("UTF-8",true));
ctx.setServletContext(servletContext);
//设置前端控制器DispatcherServlet
ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
//添加经过该控制器的所有路径地址/代表所有的亲求都经过该前端控制器
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
java
package com.example.controller;
import com.example.service.QuickService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class QuickStart {
//直接输入service使用
@Autowired
private QuickService service;
@RequestMapping("/show")
public String show(){
System.out.println("show running...."+service);
//返回视图名称,即需要展示的jsp页面名称
return "/show.jsp";
}
}
3、springmvc关键组件
1)HandlerMapping(处理映射器):用于匹配请求url和对应controller方法
2)HandlerAdapter(处理适配器):适配不同类型的controller并调用该方法
3)ViewResolver(视图解析器):对返回的视图进行解析,一般不会用到,一般前后端开发都是通过json交互的
4、示例
java
import com.example.domain.User;
import com.example.service.QuickService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/Quick")
public class QuickStart {
//直接输入service使用
@Autowired
private QuickService service;
@RequestMapping("/show")
public String show(){
System.out.println("show running...."+service);
//返回视图名称,即需要展示的jsp页面名称
return "/show.jsp";
}
@GetMapping("/show1")
public String show1(String name,int age){
System.out.println("show1..."+name+" "+age);
return "/show1.jsp";
}
@GetMapping("/show2")
public String show2(@RequestParam List<String> name){//接受list参数时,需要使用注释告诉spring,将参数封装为list
System.out.println(name.get(0));
return "/show1.jsp";
}
@GetMapping("/show3")
public String show3(@RequestParam Map<String,Object> map){//接受map参数时,需要使用注释告诉spring,将参数封装为map
map.forEach((k,v)->{
System.out.println(k+"---"+v);
});
return "/show1.jsp";
}
@GetMapping("/show4")
public String show4(@RequestParam("username") String name,int age){//入参名字和接收名字不一样时,用注释指定名字
System.out.println("show4..."+name+" "+age);
return "/show1.jsp";
}
@GetMapping("/show5")
public String show5(@RequestParam(value = "username",required=true) String name,int age){//入参名字和接收名字不一样时,用注释指定名字,设置required是该参数必填
System.out.println("show4..."+name+" "+age);
return "/show1.jsp";
}
//http://localhost:8080/demo14_war_exploded/show6?name=zhangsan&age=9&hobbys=q&hobbys=u&birth=2023/9/9&address.city=tj&address.agea=44
@GetMapping("/show6")
public String show6(User user){//接收对象
System.out.println(user);
return "/show1.jsp";
}
@PostMapping ("/show7")
public String show7(@RequestBody String user){//将请求体的数据封装到字符串里
System.out.println(user);
return "/show1.jsp";
}
@PostMapping ("/show8")
public String show8(@RequestBody String body){//将请求体的数据封装到字符串里
//使用jackson进行转换,间json格式的字符串转化为user对象
ObjectMapper mapper = new ObjectMapper();
try {
User user = mapper.readValue(body,User.class);
System.out.println(user);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return "/show1.jsp";
}
@PostMapping ("/show9")
public String show9(@RequestBody User user){//将请求体的数据封装到字符串里
System.out.println(user);
return "/show1.jsp";
}
@GetMapping ("/show10/{id}/{xxx}")//refu风格的提交方式
public String show10(@PathVariable("id") int id,@PathVariable("xxx") String name){
System.out.println(id);
System.out.println(name);
return "/show1.jsp";
}
@PostMapping("/show11")
public String show11(@RequestBody MultipartFile myfile) throws IOException {
System.out.println(myfile);
//获得当前文件的输入流
InputStream inputStream = myfile.getInputStream();
//获得上传文件的输出流
OutputStream outputStream = new FileOutputStream("D:\\"+myfile.getOriginalFilename());
//文件拷贝
IOUtils.copy(inputStream,outputStream);
//关闭流资源
inputStream.close();
outputStream.close();
return "/show1.jsp";
}
@GetMapping ("/show12")//获取指定头信息
public String show12(@RequestHeader("Accept-Encoding") String headervalue){
System.out.println(headervalue);
return "/show1.jsp";
}
@GetMapping ("/show13")//获取所有头信息
public String show13(@RequestHeader Map<String,String> map){
map.forEach((k,v)->{
System.out.println(k+":"+v);
});
return "/show1.jsp";
}
@GetMapping ("/show14")//获取所有头信息
public String show14(@CookieValue("JSESSIONID") String jsessionid){
System.out.println(jsessionid);
return "/show1.jsp";
}
@GetMapping ("/show15")//间信息存入request域中
public String show15(HttpServletRequest request){
//向request域中存数据
request.setAttribute("name","name");
return "/show16";
}
@GetMapping ("/show16")//间信息存入request域中
public String show16(@RequestAttribute("name") String name){
//从request域中取出值
System.out.println(name);
return "/show1.jsp";
}
@GetMapping ("/show17")//获取request和response对象
public String show17(HttpServletRequest request, HttpServletResponse response){
System.out.println(request);
System.out.println(response);
return "/show1.jsp";
}
}
5、客户端浏览器和服务器的同步数据交换方式,通过重定向redirect、转发forward来实现
6、客户端浏览器和服务器的异步数据交换方式:通过Ajax实现,通过创建XMLHttpRequest对象,可以向服务器发送请求和接收响应,使用open()方法初始化一个请求。这个方法接收三个参数:请求类型(如GET或POST)、请求的URL和一个布尔值表示是否异步,通过监听onreadystatechange事件等待请求的状态变化,比如请求状态变为200,表示请求成功得到了返回,使用send()方法发送请求,在回调函数中,根据请求的状态和响应内容进行处理。通常会检查readyState是否为4(请求完成)和status码是否表示成功
java
@RestController
public class ResponseController {
@RequestMapping("/res1")
public String res1(){//重定向方式
return "redirect:show.jsp";
}
@RequestMapping("/res2")
public String res2(){//转发方式
return "forward:show.jsp";
}
@RequestMapping("/res3")
public ModelAndView res3(ModelAndView modelAndView){//转发方式带数据
//封装模型数据和视图名
//设置模型数据
User user = new User();
user.setName("zhangsan");
user.setAge(19);
modelAndView.addObject("user",user);
//设置视图名称,再页面中展示模型数据
modelAndView.setViewName("/show.jsp");
return modelAndView;
}
@RequestMapping("/res4")
@ResponseBody //告诉springmvc,返回值为响应体
public String res4(){//直接展示字符串
return "modelAndView";
}
@RequestMapping("/ajax//res5")
@ResponseBody //告诉springmvc,返回值为响应体
public String res5() throws JsonProcessingException {//异步方式返回数据
User user = new User();
user.setName("zhangsan");
user.setAge(19);
ObjectMapper mapper = new ObjectMapper();
String jsonstr = mapper.writeValueAsString(user);
return jsonstr;
}
@RequestMapping("/ajax//res6")
//@ResponseBody //告诉springmvc,返回值为响应体,可以将返回值实体自动转换为json格式返回
public User res6() throws JsonProcessingException {//异步方式返回数据
User user = new User();
user.setName("zhangsan");
user.setAge(19);
return user;
}
}
7、springmvc拦截器:interceptor位于前端控制器dispatcherservlet后,拦截通过之后,才会到达对应的controller,主要拦截controller请求
1)prehandle:对请求进行拦截,返回true才能访问controller
2)posthandle:在执行controller方法执行之后执行,比如对其返回的视图进行处理
3)aftercompletion:在视图渲染完毕之后,进行最后的处理,比如对请求中的异常进行处理
多个拦截器对象,执行顺序就是addInterceptors的顺序,如果先后addInterceptors interceptor1和interceptor2,内部方法执行顺序prehandle1,prehandle2,posthandle2,posthandle1,aftercompletion2,aftercompletion1,因为内部执行时,循环遍历的顺序不一样,prehandle从前往后,posthandle从后往前,aftercompletion从后往前,如果interceptor2返回false,那么直接跳到aftercompletion1,因为两个拦截器有一个返回false,则无法到达controllor,posthandle都不执行
java
@Configuration
@EnableWebMvc
@ComponentScan("com.example")
public class MymvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/page/*")
.addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Myinterceptor())
.addPathPatterns("/**");
}
}
java
@Component
public class Myinterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle执行");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion执行");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
8、前端控制器
1)DispatcherServlet是springmvc的入口,本质是一个servlet,它在初始化时,获得了一个springmvc的ApplicationContext容器,并向容器中注册springmvc的九大组件
java
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);//文件处理器
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);//处理器映射器
initHandlerAdapters(context);//处理器适配器
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);//视图解析器
initFlashMapManager(context);
}