Spring MVC详解

Spring MVC详解

所有的控制器的处理都由servlet进行处理,是最好的MVC设计,与Struts2.x框架的区别在于,Struts2.x的控制器是由过滤器进行处理,而Spring MVC的控制器是由servlet进行控制的。

注意:

  1. MVC代码分层后,程序性能会降低
  2. SpringMVC解决了数据库的连接问题,优化了数据库与dao层。

Spring框架搭建

1、导入pom依赖

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <skipTests>true</skipTests> <!--mvn命令打包跳过test-->
</properties>
<dependencies>
            <!--            spring-mvc核心依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.2.9.RELEASE</version>
            </dependency>

            <!--            servlet依赖-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
            </dependency>

            <!--        spring-mvc,返回页面的对象转换为json对象-->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.9.8</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.8</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.9.8</version>
            </dependency>

<!--            文件上传依赖-->
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.4</version>
            </dependency>


            <!--            日志与测试-->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.13.3</version>
            </dependency>

            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
                <version>2.13.3</version>
            </dependency>

            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

2、配置spring-mvc.xml核心文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--    开启注解扫描-->
    <context:component-scan base-package="cn.mldn.lxh"/>

    <!--    开启mvc注解支持,支持controller注解的扫描,并且将转换器注册到注解驱动中 -->
    <mvc:annotation-driven conversion-service="factoryBean"/>

    <!--    类型转换器-->
    <bean id="factoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!--                使用自定义的转换器-->
                <bean class="cn.mldn.lxh.util.DateConverter"/>
            </set>
        </property>
    </bean>

    <!--    视图解析器,视图解析器进行视图解析,将逻辑视图转换为物理视图-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

<!--    定义文件上传配置-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
        <!--        每次文件上传大小限制,定位B-->
        <property name="maxUploadSize" value="102400000"/>
    </bean>

    <bean class="cn.mldn.lxh.exception.GlobalExcetionController" id="excetionController"/>
</beans>

3、自定义SpringMvc类型转换器

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return df.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Spring MVC常用注解

  1. @Controller: 【作用在类上】表示此类为Action控制器
  2. @ControllerAdvice **【作用在类上】**表示此类为全局异常处理器
    (1)@ExceptionHandler(Exception.class) **【作用在方法上】**表示此方法用来处理捕获到的指定异常
  3. @RestController 【作用在类上】表示此类所有的方法都返回json数据,并且表示此类为Action控制器
  4. @RequestMapping: 【作用在类,方法上】表示此Action主路经,或者为此Action中方法的子路径
  5. @Nullable | @NotNull【作用在方法参数上】表明可为空的参数和以及返回值。这样就够在编译的时候处理空值而不是在运行时抛出NullPointerExceptions。

1.1 @RequestParam

@RequestParam主要用于在SpringMVC后台控制层获取参数时,前端传入的参数和方法形参不一致时。

它支持三个属性:

  • value:默认属性,用于指定前端传入的参数名称
  • name:默认属性(同value属性一样)。
  • required:用于指定此参数是否必传 ,默认值true。
  • defaultValue:当参数为非必传参数且前端没有传入参数时,指定一个默认值。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rl5PjdAl-1605769837811)(imgs/image-20200418184356186.png)]

1.2 @RequestHeader

@RequestHeader主要用于从请求头中获取参数。它支持的属性跟@RequestParam一样。
在这里插入图片描述

1.3 @CookieValue

@CookieValue 用于从cookie中取值,它支持的属性跟@RequestParam一样。

在这里插入图片描述

1.4 @RequestBody

@RequestBody用于接收前端传入的消息体,注意:只有POST请求才有消息体。

在这里插入图片描述

它的另一个主要用法是用于接收Ajax提交的异步数据(说白了,就是前段传递的json格式字符串)。

前端发送请求

<script type="application/javascript" src="js/jquery.js"></script> 
<script> 
    $(function () { 
   		$("#sub").click(function () { 
        	$.ajax({ type:"POST",
                    url:"${pageContext.request.contextPath}/demo3", 
                    contentType:"application/json", 
                    dataType:"json", 
                    data:'{"name":"tom","age":"14"}', 
                    success:function(data){     
                    } 
              }); 
        }); 
	}) 
</script>

后端响应请求

public String demo3(@RequestBody String body){} 
public String demo3(@RequestBody User user){}

注意:@RequestBody和@ResponseBody都是用来干什么的?

  • @RequestBody主要是接收前段传递的json格式字符串,如果是字符串本质是对象,就转换为对应的对象类型;
    -@ResponseBody主要是直接返回字符串,如果字符串本质是对象,就转换为json格式。

1.5 @PathVariable

REST风格:

REST是一种软件架构风格,或者说是一种规范,其强调HTTP应当以资源为中心。
它规范了HTTP请求动作,使用四个词语分别表示对资源的CRUD操作:
GET(获取)、POST(新建)、PUT(更新)、DELETE(删除)

在这里插入图片描述
@PathVariable就是用来从Rest风格的URL中获取参数的注解 。

它支持三个属性:

  • value:默认属性,用于指定路径上的参数名称 。
  • name:默认属性(同value属性一样)。
  • required:用于指定此参数是否必传 ,默认值true。
//访问/demo7/Tom 
@RequestMapping("/demo7/{name}") 
public void demo7(@PathVariable String name){
    System.out.println(name)
}

1.6 @ModelAttribute

@ModelAttribute的功能主要在两方面:

  • 运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入 ModelMap中,并且放在request域对象中,便于View层使用 。

本质,就是替换之前的request.setAttribute()方法
在这里插入图片描述

  • 运用在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入 到ModelMap中 。

在这里插入图片描述

1.7@SessionAttribute

@SessionAttribute用于从session域中获取指定的参数值

@GetMapping("/panel")
public String panel(@SessionAttribute("userId") Long userId) {
		//  表示从session域中获取name=“userId”的值,并赋值给方法参数列表中的userId变量中
}

1.8 @SessionAttributes

@SessionAttributes 只能标注在类上,用来将模型中的数据存request和session域中。

使用sessionStatus.setComplete()可以销毁session。

@Controller 
@RequestMapping("/session") 
@SessionAttributes("user") 
public class SessionController { 
    @RequestMapping("/put") 
    public String put(User user,Model model) { 
        System.out.println(user); 
        user.setName("tom"); 
        user.setAge(123); 
        model.addAttribute("user",user); 
        return "redirect:/success.jsp"; 
    }
    @RequestMapping("/clear") 
    public String put(SessionStatus sessionStatus) { 
        //销毁session 
        sessionStatus.setComplete(); 
        return "redirect:/success.jsp"; 
    } 
}

Controller控制器(重点)

请求类型封装

SpringMVC支持的参数类型有:

  • 基本数据类型
  • pojo类型
  • 数组类型
  • 集合类型
1 基本类型

只需要保证前端传递的参数名称跟方法的形参名称一致就好。

SpringMVC介绍的参数默认都是String类型的,它内部会进行一个自动转型。

在这里插入图片描述

2 pojo类型

只需要保证前端传递的参数名称跟pojo的属性名称(set方法)一致就好。

在这里插入图片描述

3 数组类型

只需要保证前端传递的参数名称跟方法中的数组形参名称一致就好。

在这里插入图片描述

4 集合类型

获取集合参数时,要将集合参数包装到一个pojo中才可以。

封装一个VO对象:

在这里插入图片描述

页面跳转

1 使用request域对象封装结果

使用这种方式需要导入servlet的包:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

在这里插入图片描述

2 使用Model封装结果

在这里插入图片描述

3 使用ModelAndView封装结果

在这里插入图片描述

补充点:我们将ModelAndView和Model这些由框架给我们准备好,我们直接拿过来用的对象称为隐式对象

4 扩展请求转发

使用forward关键字进行请求转发,使用原生的servlet的对象进行请求转发,这种情况下视图解析器就失效了

    // 使用forward关键字进行请求转发,这种情况下视图解析器就失效了
    @RequestMapping("/hello/result4")
    public String hello4(Model model){
         model.addAttribute("name",12);
        return "forward:/WEB-INF/success.jsp";
    }
    // 使用原生的servlet的对象进行请求转发,这种情况下视图解析器就失效了
    @RequestMapping("/hello/result5")
    public void hello5(HttpServletRequest request, HttpServletResponse response) 
        			throws ServletException, IOException {
        request.setAttribute("name",13);
        request.getRequestDispatcher("/WEB-INF/success.jsp").forward(request,response);
    }
5 扩展重定向
    // 使用redirect关键字进行重定向,这种情况下视图解析器就失效了
    @RequestMapping("/hello/result6")
    public String hello6(Model model){
        model.addAttribute("name",16);
        return "redirect:/hello/result4";
    }
    // 使用原生的servlet的对象进行重定向,这种情况下视图解析器就失效了
    @RequestMapping("/hello/result7")
    public void hello7(HttpServletRequest request, HttpServletResponse response) 
        			throws ServletException, IOException {
        request.setAttribute("name",17);
       	request.getRequestDispatcher(request.getContextPath()+"/hello/result4")
           	   .forward(request,response);
    }

直接返回结果

1 使用Response返回结果

在这里插入图片描述

2 使用@ResponseBody注解

@ResponseBody可以方法方法上,也可以方法类上,方法类上之后,类中的所有方法返回都不再是视图名了。

在这里插入图片描述
@ResponseBody需要导入依赖

 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-core</artifactId>
     <version>2.9.8</version>
 </dependency>
 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-databind</artifactId>
     <version>2.9.8</version>
 </dependency>
 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-annotations</artifactId>
     <version>2.9.8</version>
 </dependency>
3 使用@ResponseBody返回JSON数据

先要导入JSON转换需要的包:

  <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.8</version>
  </dependency>
  <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.8</version>
  </dependency>
  <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.8</version>
  </dependency>

返回一个json格式对象:

    // 使 @ResponseBody 对象返回对象
    // 如果返回的是一个对象,要使用json格式转换
    @RequestMapping("/hello/result10")
    @ResponseBody  // 作用:不再返回视图名,而是直接返回对象
    public User hello10(){
        User user = new User();
        user.setName("tom");
        user.setAge(20);
        return user;
    }

实际开发:

方式一:

1、先封装一个相应实体

// 先定义一个相应结果实体类
public class Result {
    private Integer code;  // 相应结果状态码
    private String msg;    // 相应结果信息(通常错误的时候才会有)
    private Object data;   // 相应数据(通常是正确返回,且有结果的时候)
	// 省略get,set方法
}    

2、响应前端数据

    // 使 @ResponseBody 相应一个自定义结果对象,同样要返回json格式
    @RequestMapping("/hello/result11")
    @ResponseBody  // 作用:不再返回视图名,而是直接返回对象
    public Result hello11(){
        Result result = new Result();
        result.setCode(200);
        User user = new User();
        user.setName("tom");
        user.setAge(20);
        result.setMsg("查询正常");
        result.setData(user);
        return result;
    }

方式二:

使 ResponseEntity 响应一个自定义结果对象,同样要返回json格式,可以省略@ResponseBody

// 使 ResponseEntity<T> 响应一个自定义结果对象,同样要返回json格式
// 可以省略@ResponseBody
@RequestMapping("/hello/result12")
public ResponseEntity<Result> hello12(){
    Result result = new Result();
    result.setCode(200);
    User user = new User();
    user.setName("tom");
    user.setAge(20);
    result.setMsg("查询正常");
    result.setData(user);
    return new ResponseEntity<Result>(result,HttpStatus.CREATED);
}

获取JSP内置对象

在Action方法参数中摆出内置对象就可以获取request对象和response对象,在用户通过路径访问此方法时将自动获取参数中指定的内置对象

  1. Request.getSessios() : 获取session对象
  2. Request.getServletContext() : 获取ServiceContext(application)对象

SpringMVC异常处理

在这里插入图片描述
@ControllerAdvice 【作用在类上】表示此类为全局异常处理器
@ExceptionHandler(Exception.class) 【作用在方法上】表示此方法用来处理捕获到的指定异常

//spring-mvc 全局异常处理器,在controller层抛出异常,此类可以进行捕获,并进行处理
public class GlobalExcetionController implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
//        指定错误信息
        modelAndView.addObject("msg",e.getMessage());
//        指定跳转页面
        modelAndView.setViewName("home");
        return modelAndView;
    }
}

拦截器

拦截器接口HandlerInterceptor

org.springframework.web.servlet.HandlerInterceptor >> 实现此此接口的类为拦截器

a. controller执行前拦截: (重点方法)
public boolean preHandle (HttpServletRequest request,HttpServletResponse response,Object handler)
注意:
1、方法返回true表示拦截后继续执行后续操作,返回false表示不执行后续操作
2、参数handler对象为HandlerMethod类型
3、HandlerMethod对象方法:

  1. 触发此拦截器的程序类(controller): public Object getBean();
  2. 取得处理的方法: public Method getMethod();
  3. 取得Bean的类型: public Class<?> getBeanType();
  4. 取得方法的参数数据: public MethodParameter[] getMethodParameters();
    |- 取得方法: public Method getMethod();。
    |- 取得参数名称: public String getParameterName();。
    |- 取得参数类型: public Class<?> getParameterType();。

b. controller执行后拦截: public void postHandle (HttpServletRequest request,HttpServletResponse response,
object handler,ModelAndView modelAndView)

c. 请求结束后拦截: public void afterCompletion (HttpServletRequest request,HttpServletResponse response,
object handler,Exception ex)

preHandle(): 这个方法在业务处理器处理请求之前被调用,SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

postHandle():这个方法在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行。

afterCompletion():该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

实现拦截器

拦截器主要是对Controller控制器的预处理,或者是后处理

  1. 实现HandlerInterceptor接口,并复写方法
public class SessionInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("我是拦截器:preHandle");
//        返回false请求结束,返回true,时就会继续调用下一个Interceptor 的preHandle 方法,
//        如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("我是拦截器:postHandle");
        HttpSession session = request.getSession();
        Object login_user = session.getAttribute("LOGIN_USER");
        System.out.println("用户:"+login_user);
        if (login_user == null){
            System.out.println("没有登录,请登录后操作");
            request.getRequestDispatcher(request.getContextPath()+"/index.jsp");
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("我是拦截器:afterCompletion");
    }
}
  1. 在applicationContext.xml文件中配置拦截器
<!--    注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>       <!--表示需要拦截的路径-->
            <!-- 需排除拦截的地址 -->
            <!--  <mvc:exclude-mapping path="/userController/login"/>  -->
            <bean class="cn.mldn.lxh.xmz.web.interceptor.SessionInterceptor"/>           <!--拦截器的包点类名称 -->
        </mvc:interceptor>
        <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法  -->
    </mvc:interceptors>

静态资源映射

1 路径匹配规则

在servlet中的url-pattern有四种匹配方式:

  1. 精确匹配 /abc/index.jsp /a/b.jpg /abc/a/b/c/a.css

  2. 路径匹配 /abc/* /* [要求必须是/开头,以*结尾]

  3. 扩展名匹配 *.jsp *.html .do [要求必须以.开头]

  4. 默认(缺省)匹配 /

四种匹配方式的优先级:精确 > 路径 > 扩展名 > 默认

2 几个Servlet的作用

DefaultServlet (可以定位静态资源css html image js等) / 默认匹配

JspServlet(可以解析jsp文件) *.jsp 扩展名匹配

DispatcherServlet(可以根据URL寻找控制器)

DispatcherServlet配置
只有DispatcherServlet生效,这样所有的请求都会交给它处理,处理不了就报错

DispatcherServlet配置
DispatcherServlet和jsp生效,而且jsp的优先级要高,也就是访问jsp的请求由jsp的servlet的处理,其它请求由DispatcherServlet处理,处理不了就报错

当配置为 / 的情况下,思考:

  • 如果访问了一个jsp文件,他能处理吗? 能
  • 如果我访问的是一个jpg css js文件,他能处理吗? 不能

结论:
当我们的 dispatcherServlet 配置为/的时候.css js image等静态资源访问不了了。

怎么办?

  • 把dispatcherServlet 配置改为*.do类似后缀的请求,然后所有映射器处理的请求,后缀必须带上.do,比如:http://localhost:8080/hello/requestParam.do;
  • 使用Spring MVC提供的静态资源释放方式(见下)。

3 DispatcherServlet配置 / 和 /* 的区别

DispatcherServlet配置 /

只有DispatcherServlet生效,这样所有的请求都会交给它处理,处理不了就报错

DispatcherServlet配置 /*

DispatcherServlet和jsp生效,而且jsp的优先级要高,也就是访问jsp的请求由jsp的servlet的处理,其它请求由DispatcherServlet处理,处理不了就报错

当配置为 / 的情况下,思考:

  • 如果访问了一个jsp文件,他能处理吗? 能
  • 如果我访问的是一个jpg css js文件,他能处理吗? 不能

结论:

当我们的 dispatcherServlet 配置为/的时候.css js image等静态资源访问不了了。

怎么办?

  • 1、把dispatcherServlet 配置改为*.do类似后缀的请求,然后所有映射器处理的请求,后缀必须带上.do,比如:http://localhost:8080/hello/requestParam.do;
  • 2、使用Spring MVC提供的静态资源释放方式(见下)。

4 释放静态资源配置

我们现在的DispatcherServlet配置的路径是/,即这是个默认的Servlet,只要是请求找不到对应Servlet都
会转交到它这里来,而它又会去调用适配器映射器去寻找对应的Hadler处理。
但是对于一些静态资源像js、css是不需要Handler处理的,所以要告诉DispatcherServlet,哪些请求不
需要找Handler处理,而是直接去找对应的资源,这就用到了一个配置 :

< mvc:resources mapping="匹配请求路径" location="真实路径"> 
< mvc:resources mapping="匹配请求路径" location="真实路径"> 
<!--只要是请求路径为/js/**的,不去寻找对应的Controller,而是直接到对应的路径/js下取资源--> 
<mvc:resources mapping="/js/**" location="/js/" />

或者是:

<!--这个配置也可以:自己找不到资源的抛给外层容器处理--> 
<mvc:default-servlet-handler />

哪些方式可以处理SpringMVC的静态资源

  1. 使用容器默认servlet标签defaultServlet来处理静态文件
  2. mvc:resources标签
  3. mvc:default-servlet-handler/标签
  4. 给DispatcherServlet拦截的url加后缀

其他重点

类型转换器

在controller控制器中,自定义方法转换器将程序中的日期时间进行转换为程序可用类型,否则会报错

方式一

//    日期时间转换器
@InitBinder //表示数据转换绑定器
public void initBinder(WebDataBinder binder){
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        注册一个专门的日期转换器的操作类,并且容许数据为空
   binder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,true));
}

方式二

// 1、 定义类型转换器
public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return df.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}
<!--    开启mvc注解支持,支持controller注解的扫描,并且将转换器注册到注解驱动中 -->
<mvc:annotation-driven conversion-service="factoryBean"/>

<!--    类型转换器-->
<bean id="factoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <!--                使用自定义的转换器-->
            <bean class="cn.mldn.lxh.util.DateConverter"/>
        </set>
    </property>
</bean>

中文乱码过滤器

  1. 使用Spring提供的CharacaterEncodingFilter过滤器处理
  2. 在web.xml文件中定义过滤器
<!-- 解决post请求乱码:增加tomcat过滤器配置 -->
   <filter>
   		<filter-name>encodingFilter</filter-name>
   		<filter-class>
   			org.springframework.web.filter.CharacterEncodingFilter
   		</filter-class>
   		<init-param>
   			<param-name>encoding</param-name>
   			<param-value>UTF-8</param-value>
   		</init-param>
   </filter>
   <filter-mapping>
   		<filter-name>encodingFilter</filter-name>
   		<url-pattern>/*</url-pattern>
   </filter-mapping>

错误页跳转问题

解决方案一:配置web.xml文件
在这里插入图片描述
注意:表示页面出现500或者404将跳转到errors.jsp页面,进行显示

怎么理解springmvc

SpringMVC是基于MVC设计模式的框架,M,V,C,各个层级分工明确,

MVC:

  • M(model模型):数据表的实体类
  • V(view视图):jsp页面
  • C(controller控制器):接受请求,并根据请求调用相应的业务逻辑,根据业务逻辑返回对应的view视图,以及model(模型数据)

好处:

  1. 显示逻辑与业务逻辑的相分离,实现业务逻辑的复用
  2. MVC分层分工明确,团队开发时,能更好的分工合作,以及后期方便代码维护

问题:
1. hibernate与mybatis的联系与区别

联系:

  • hibernate与mybatis都是持久层的框架,封装的是持久化操作

区别:

  • hibernate是全自动的框架,提供了以完全面向对象的方式操作数据库,同时以会自动封装查询到的数据,对于系统要求比较高的情况下必须对hibernate的配置非常熟悉,才能达到要求,学习成本是很高的(会自动生成sql语句、
  • mybatis是半自动的框架,与hibernate相比需要手写sql语句所以是半自动,我们可以自己编写SQL语句,可以满足系统性能的要求,学习成本是比较低的

2. model1 与 model2 的区别

Model1:jsp承担了view显示,与servlet控制器的角色,缺点,分工不明确,不方便后期维护
Model2:jsp -》 servlet -》 model 经典的mvc模式

SSM:是基于三层框架,搭建的一个整合框架(上层组件依赖下层组件)

表现层: 负责页面的显示逻辑,代表了MVC设计模式的VC两个模块
业务层(service):负责具体的业务逻辑
逻辑层(dao):负责数据库的打开,与关闭

项目问题:

  1. java项目properties与xml资源文件打包问题
    Java项目中,可能会存在默认不为properties与xml资源文件打包,需要以下配置
<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
    </resource>
</resources>
  1. 测试注意:先测试后端接口,再测试前端发出的请求
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值