@Controller

  1. Java类标记为控制器类,方便扫描添加到IOC容器中。

@RequestMapping

  1. @RequestMapping的作用将请求和处理请求的控制器建立一个映射关系。
  2. 标记在类上: 定义同意路径规则,相当于组。
  3. 标记在方法上: 定义具体映射规则,唯一路径。
  4. String[] value: 指定请求路径,如果只有一个参数可以默认不写,能够匹配多个请求。
  5. String[] method: 接收请求类型,可以设置种或多种请求方式,默认是全部请求都处理。
  6. ["RequestMethod.GET","RequestMethod.POST","RequestMethod.PUT","RequestMethod.DELETE"]
  7. [@GetMapping, @PostMapping, @PutMapping, @DeleteMapping]
  8. String[] params: "username=root" 请求必须携带username参数并且username等于root
  9. 通过Headers控制请求头,限制只有firefox浏览器才能访问此资源
  10. String[] headers: "User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0"
  11. Spring MVC支持Ant风格:
  12. 1.value="/a?a/ant": ? 表示匹配任意单个字符
  13. 2.value="/a*a/ant": * 表示匹配零个或多个字符
  14. 3.value="/a**a/ant": ** 表示匹配一级或多级目录
  15. Spring MVC支持Restful风格: 参数占位符
  16. value="/rest/{id}" 接收参数: @PathVariable("id") Integer id

原生 Servlet API

  1. //原生Servlet API获取参数
  2. HttpServletRequest request
  3. String[] ops = request.getParameterValues("op");
  4. for (String op : ops) {
  5. System.out.println(op);
  6. }

控制器形参获取参数

  1. 处理器形参中的参数名要与实参参数名保持一致。
  2. 如果接收多个同名参数就使用数组 String[] op
  3. 参数重命名,非必须传入参数,参数默认值为root
  4. @RequestParam(value = "username",required = false,defaultValue = "root") String user_name
  5. 获取请求头信息
  6. @RequestHeader(value = "Host",required = false,defaultValue = "localhost:8080") String host
  7. 获取Cookie
  8. @CookieValue(value = "JSESSIONID",required = false,defaultValue = "mycookie") String cookie
  9. 如果参数为一个实体对象,则可以直接用实体类作为形参接收

视图模型ModelAndView

  1. @RequestMapping(value = "/request")
  2. public ModelAndView request() {
  3. //创建视图模型
  4. ModelAndView modelAndView = new ModelAndView();
  5. //处理模型数据,向请求域request共享数据
  6. modelAndView.addObject("framework","Spring Cloud");
  7. //添加Map集合 addAllObjects(Map<String,?>)
  8. //设置视图名称
  9. modelAndView.setViewName("request");
  10. return modelAndView;
  11. }
  12. //Model,ModelMap,Map之间的关系
  13. 最终实现都是BindingAwareModelMap类,类依赖关系如下
  14. BindingAwareModelMap extends ExtendedModelMap
  15. ExtendedModelMap extends ModelMap implements Model
  16. ModelMap extends LinkedHashMap<String, Object>
  17. //封装视图模型
  18. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

域对象处理

  1. 1.在方法参数添加HttpSession session即可使用原生API
  2. 2.ServletContext application = session.getServletContext(); //application域处理

网络资源视图

  1. "forward:/resourcePath" //转发
  2. "redirect:/resourcePath" //重定向

RestFul风格

  1. GET:资源获取 POST:资源创建 PUT:资源更新 DELETE:资源删除

报文信息转换器

  1. HttpMessageConverter
  2. @RequestBody 封装参数
  3. @ResponseBody 回写数据
  4. RequestEntity 封装完整请求参数[包括请求头等]
  5. ResponseEntity 静态类,可以设置完整响应信息[包括响应头等]

文件上传下载

  1. <!-- 文件上传依赖 -->
  2. <dependency>
  3. <groupId>commons-fileupload</groupId>
  4. <artifactId>commons-fileupload</artifactId>
  5. <version>1.3.3</version>
  6. </dependency>
  7. <!-- CommonsMultipartResolver规则配置 -->
  8. <bean id="multipartResolver"
  9. class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  10. <property name="defaultEncoding" value="utf-8"></property>
  11. <!-- 1024 * 1024 * 20 = 20M -->
  12. <property name="maxUploadSize" value="20971520"></property>
  13. <property name="maxInMemorySize" value="20971520"></property>
  14. </bean>
  15. <!-- 前端文件上传下载格式 -->
  16. <a th:href="@{/fileDown}">文件下载</a><br/>
  17. <form th:action="@{/fileUp}" method="post" enctype="multipart/form-data">
  18. 上传文件<input type="file" name="photo"/><br/>
  19. <input type="submit" value="上传"/>
  20. </form>
@RequestMapping(value = "/fileDown")
public ResponseEntity<byte[]> json(HttpSession session) {
    //获取ServletContext对象
    ServletContext servletContext = session.getServletContext();
    //获取服务器中资源真实路径
    String realPath = servletContext.getRealPath("/static/bin/DMS.exe");
    //文件流处理
    FileInputStream in = null;
    ResponseEntity<byte[]> responseEntity = null;
    try {
        in = new FileInputStream(realPath);
        byte[] bs = new byte[in.available()];
        in.read(bs);
        //创建HttpHeaders对象
        MultiValueMap<String,String> headers = new HttpHeaders();
        //设置下载方式及其文件名称
        headers.add("Content-Disposition","attachment;filename=MSD.exe");
        //响应状态码
        HttpStatus statusCode = HttpStatus.OK;
        //创建ResponseEntity对象
        responseEntity = new ResponseEntity<>(bs,headers,statusCode);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return responseEntity;
}

@ResponseBody
@RequestMapping(value = "/fileUp")
public String fileUp(MultipartFile photo,HttpSession session) {
    //获取服务资源路径
    String realPath = session.getServletContext().getRealPath("/static/jar/");
    File file = new File(realPath);
    if (!file.exists()){
        System.err.println(realPath);
        file.mkdir();//创建目录
    }
    //获取文件名
    String originalFilename = photo.getOriginalFilename();
    String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
    String uuid = UUID.randomUUID().toString();
    String uuidFile = uuid+suffixName;
    //File.separator:文件分隔符
    String fileName = realPath+File.separator+uuidFile;
    try {
        photo.transferTo(new File(fileName));
        return "success";
    } catch (IOException e) {
        return "fail";
    }
}

Spring MVC 拦截器

Filter是基于函数回调的,而Interceptor则是基于Java反射的,
拦截器主要作用于拦截控制器的方法,过滤器作用于Servlet容器。
在action的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
执行流程:    过滤前-拦截前-action执行-拦截后-过滤后
多拦截器: 
1.先配置的拦截器bean先触发执行。
2.拦截器1pre-拦截器2pre-action执行-拦截器2post-拦截器1post-拦截器2after-拦截器1after。
<!--   文件上传解析器,将上传的文件封装为MultipartFile     -->
<bean id="multipartResolver" 
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!--   配置拦截器[默认拦截所有请求]     -->
<bean id="testInterceptor" class="com.example.interceptors.TestInterceptor"/>
<mvc:interceptors>
  <mvc:interceptor>
    <mvc:mapping path="/testInterceptor"/>
    <ref bean="testInterceptor"/>
  </mvc:interceptor>
</mvc:interceptors>
public class TestInterceptor implements HandlerInterceptor {
    //任务执行前处理
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) throws Exception {
        System.err.println("任务执行前处理");
        return true;//true放行下一步执行
    }
    //任务执行后处理
    @Override
    public void postHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler, 
                           ModelAndView modelAndView) throws Exception {
        System.err.println("任务执行后处理");
    }
    //视图渲染后处理
    @Override
    public void afterCompletion(HttpServletRequest request, 
                                HttpServletResponse response, 
                                Object handler, 
                                Exception ex) throws Exception {
        System.err.println("视图渲染后处理");
    }
}

异常处理器

处理控制器执行过程中所发生的异常。
<!--   配置异常处理映射解析器     -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
    <props>
        <prop key="java.lang.ArithmeticException">error</prop>
    </props>
</property>
<!--   捕获异常共享到Request域中     -->
<property name="exceptionAttribute" value="ex"/>
</bean>
@ControllerAdvice
public class TestExceptionHandler {
    //vaue为数组类型,可以定义多种异常类型
    @ExceptionHandler(value = {ArithmeticException.class})
    public String testExceptionHandler(Exception ex, Model model) {
        model.addAttribute("ex", ex);
        return "error";
    }
}

Spring MVC - Ajax跨域问题

Ajax工程

//webpack工程
import $ from 'jquery';
$(function() {
    $("#btn").click(function() {
        $.ajax({
            type: 'get',
            url: 'http://localhost:8080/emp',
            contentType: "application/json;charset=UTF-8",
            dataType: 'json',
            success: function(data) {
                console.log(data);
            }
        });
    });
});

局部跨域

/**
 * origins:允许可访问的域列表
 * maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
 */
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class AjaxController {
    @GetMapping(value = "/emp")
    public Employee emp() {
        return new Employee(1,"特朗普",74,'男');
    }
}

全局跨域

//全局跨域
@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**");
        }
    };
}

Spring MVC 注解驱动开发

Config

//Web工程的初始化类
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    //指定Spring配置
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    //指定Spring MVC配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMVCConfig.class};
    }
    //配置url映射路径
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    //过滤器规则配置
    @Override
    protected Filter[] getServletFilters() {
        //设置字符编码过滤器
        CharacterEncodingFilter encoding = new CharacterEncodingFilter();
        encoding.setEncoding("UTF-8");
        encoding.setForceResponseEncoding(true);
        //设置隐藏方法过滤器
        HiddenHttpMethodFilter hiddenMethod = new HiddenHttpMethodFilter();
        return new Filter[]{encoding, hiddenMethod};
    }
}
@EnableWebMvc//开启MVC注解驱动
@Configuration//表示为Spring配置类
@ComponentScan(basePackages = "com.example.controller")//扫描控制器
public class WebMVCConfig implements WebMvcConfigurer {
    //配置生成模板解析器
    @Bean
    public ITemplateResolver templateResolver() {
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        assert webApplicationContext != null;
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
                Objects.requireNonNull(webApplicationContext.getServletContext()));
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }
    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }
    //生成视图解析器并未解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
    //视图控制器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }
    //静态资源处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
    //文件上传解析器
    @Bean
    public MultipartResolver multipartResolver() {
        return new CommonsMultipartResolver();
    }
    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestInterceptor())
        .addPathPatterns("/hello");//添加拦截规则
    }
    //异常处理器
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver exceptionResolver =
                new SimpleMappingExceptionResolver();
        Properties prop = new Properties();
        prop.setProperty("java.lang.ArithmeticException","error");
        exceptionResolver.setExceptionMappings(prop);
        exceptionResolver.setExceptionAttribute("ex");
        resolvers.add(exceptionResolver);
    }
}
@Configuration
public class SpringConfig {
}

Interceptor

public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse
                             response,
                             Object handler) throws Exception {
        System.err.println("preHandle");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.err.println("postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        System.err.println("afterCompletion");
    }
}

Controller

@Controller
public class TestController {
    @RequestMapping("/")
    public String index() {
        return "index";
    }
    @RequestMapping("/test")
    public void test() {
        System.out.println(4/0);
    }
}

Spring MVC 执行流程

1.Http请求发送到Tomcat服务器,先通过Servlet容器,执行Filter和Service方法。
2.请求到达DispatcherServlet,将请求转发到HandlerMapping,查找url映射的控制器。
3.将查找到的控制器和拦截器信息封装成一个执行链返回给DispatcherServlet。
4.先执行控制器前置拦截器,然后执行控制器适配器,最后执行控制器。
5.成功执行控制器后得到ModelAndView视图模型并返回,然后执行控制器后置拦截器。
6.DispatcherServlet接收到ModelAndView后交给视图解析器执行解析视图。
7.视图解析器解析出视图后返回给DispatcherServlet进行视图渲染,渲染完成后执行渲染后拦截器,响应用户。

火狐截图_2021-08-06T07-10-28.572Z.png