Spring MVC:第二天

1.WEB-INF目录资源介绍

在一些特定的项目中,从安全性等方面考虑不希望客户端通过浏览器直接访问对应的资源。

这时就可以把资源放入到WEB-INF目录中。因为在Java Web项目中规定:WEB-INF中资源是不允许被客户端直接访问,需要先访问控制器,通过控制器的转发来访问这些资源。

这种目录结构也更加负责MVC开发模式,更能体现出控制器的作用。

2.视图解析器

Spring MVC的控制单元 支持 ModelAndView、String 等多种类型的返回值,但无论控单元的返回值是哪种类型,Spring MVC 内部最终都会将它们封装成一个 ModelAndView 对象,它由 model(模型数据)和 view(逻辑视图名)两部分组成,所以 Spring MVC 需要借助 ViewResolver(视图解析器)将 逻辑视图名解析为真正的 View 视图对象,然后才能响应给客户端展示。

Spring MVC 的核心理念是将 视图与 数据模型进行解耦,视图技术随场景选择:Thymeleaf、JSP、FreeMarker、Excel 等等。

视图解析器用来解析逻辑视图,将其解析成真正的视图对象。

SpringMVC 提供了一个视图解析器的接口 ViewResolver,所有具体的视图解析器必须实现该接口。

AbstractCachingViewResolver:抽象类,这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找,如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的map中,接着再把新建的视图返回。使用这种视图缓存的方式可以把解析视图的性能问题降到最低。
UrlBasedViewResolver:它是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。如prefix=/WEB-INF/,suffix=.jsp,返回的视图名称viewName=test,则UrlBasedViewResolver解析出来的视图URL就是/WEB-INF/test.jsp。默认的prefix和suffix都是空串。
InternalResourceViewResolver:它是URLBasedViewResolver的子类,所以URLBasedViewResolver支持的特性它都支持。在实际应用中InternalResourceViewResolver也是使用的最广泛的一个视图解析器。InternalResourceViewResolver解释为内部资源视图解析器。InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型数据都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword到目标URL
ThymeleafViewResolver:Thymeleaf视图解析器,映射成一个 Thymeleaf 模板文件。
FreeMarkerViewResolver:UrlBasedViewResolver的子类。FreeMarkerViewResolver会把Controller处理方法返回的逻辑视图解析为FreeMarkerView。

解析过程

ModelAndView 模型数据(存储业务数据)和视图

        model:模型数据(存储模型层中查到的数据)

        view:视图(页面属于视图的一种)

控制单元执行完成后,无论什么类型返回值,都会封装为ModelAndView

        底层源码:

                ModelAndView mv;

                mv=ha.handle(processedRequest, response, mappedHandler.getHandler());

                执行控制单元,控制单元返回结果封装为ModelAndView。

控制单元返回的结果固定被封装为ModelAndView。

视图解析器:ViewResolver(接口),解析不同的视图,使用不同的实现类

        视图解析器,解析控制单元返回的ModelAndView,经过解析返回具体的View对象。

视图解析器解析JSP执行过程:

        1.控制单元返回值固定封装为ModelAndView。例如:View Name:/index.jsp

        2.render():渲染方法

                1.解析出视图的名称。/index.jsp

                2.根据视图名称获取对应的视图解析器(默认使用:InternalResourceViewResolver)

                3.通过InternalResourceViewResolver解析返回View对象(jsp返回InternalResourceView)

                4.InternalResourceView.render()视图渲染(将model中的数据通过view,向客户端完成响应)

                        1.将Model中的数据存储到request域对象中

                        2.将请求转发到index.jsp。

自定义视图解析器

<!--其中id="viewResolver"的取值是任意的,也可以省略id属性不写。-->
<!--配置自定义试图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 前缀 -->
    <property name="prefix" value="/WEB-INF/page/"></property>
    <!-- 后缀 -->
    <property name="suffix" value=".jsp"></property>
</bean>
@RequestMapping("/showSuiyi")
public String showSuiyi(){
    return "suiyi";// 由视图解析器拼接:prefix + suiyi + suffix。具体:/WEB-INF/page/ + suiyi + .jsp
}

@RequestMapping("/showSuiyi2")
public String showSuiyi2(){
    return "suiyi2";// 由视图解析器拼接:prefix + suiyi + suffix。具体:/WEB-INF/page/ + suiyi2 + .jsp
}

当自定义视图解析器后,返回值前面和后面都会固定拼接字符串(在没有使用其他注解情况下)。但是如果控制单元执行完,并不希望跳转到视图,而是跳转到控制器,这时需要在返回值前面明确添加forward:或redirect: ,这样就不走视图解析器了。

3.静态资源放行

按照SpringMVC的使用流程,需要在web.xml文件中配置DispatcherServlet的拦截范围,而我们配置的拦截范围为”/”,表示拦截除jsp请求以外的所有请求。这样造成,请求是js,css,图片等静态资源的请求,也会被拦截,调用对应的单元方法来处理请求。但是,我们是一个静态资源的请求,不应该按照普通单元方法请求的流程来处理,而是将对应的静态资源响应给浏览器使用。

Spring MVC 支持静态资源配置,当URL满足指定路径要求时不再去找控制单元,而是直接转发到特定路径中静态资源。

需要在springmvc.xml中配置静态资源放行

<!--配置静态资源放行-->
	<!--mapping:当URI是什么样格式时,不再执行控制器,而是寻找静态资源。 ** 是通配符,表示任意层路径 -->
	<!--location:去哪个目录中寻找静态资源。mapping中**的值是什么,就去location目录中找对应资源-->
	<!--例如URL是http://localhost:8080/bjsxt/js/jquery.js 其中mapping的**就是jquery.js,就会去location的/js/目录中寻找jquery.js -->
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
<mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
<mvc:resources mapping="/images/**" location="/images/"></mvc:resources>

如果把静态资源放在WEB-INF中

<mvc:resources mapping="/js/**" location="/WEB-INF/js/"></mvc:resources>
<mvc:resources mapping="/css/**" location="/WEB-INF/css/"></mvc:resources>
<mvc:resources mapping="/images/**" location="/WEB-INF/images/"></mvc:resources>

4.控制单元的方法参数(接收请求参数)

1.控制单元方法参数写法

控制单元方法参数一共有两种写法:

(1)紧耦方式:获取原生Servlet API,通过原生Servlet API获取请求参数、设置响应内容、设置作用域的值。

(2)解耦方式:使用Spring MVC提供的方式获取请求参数、设置响应内容、设置作用域的值。

2.紧耦方式

在Spring MVC中,可以直接在控制单元的方法参数中按需注入HttpServletRequest、HttpServletResponse、HttpSession对象。注入后就可以像之前学习Servlet一样进行获取参数。

例如:

@RequestMapping("/demo")
public String demoServlet(HttpServletRequest req){
    String name = req.getParameter("name");
    return "index";
}

输出响应内容也和之前学习Servlet的时候是类似的,但是需要注意控制单元返回值为void

作用域传值也是和之前Servlet中学习的一样,只需要在参数中注入作用域对象就可以了。但是需要注意ServletContext不能直接注入,需要通过其他对象获取。HttpServletRequest和HttpSession可以注入。

这种需要在控制单元方法参数中注入Servlet API的方式,称为Spring MVC 紧耦方法。因为使用的是原生Servlet API,和原生Servlet API紧耦。

3.解耦方式

解耦方式是Spring MVC独有方式。是Spring MVC给开发者提供的:

(1)获取请求中内容

(2)设置作用域值

(3)设置响应内容

1.获取请求中内容

 请求参数根据参数的类型分为多种写法。

 1.获取普通表单参数

 获取普通表单参数,只需要包含在控制单元中提供与请求参数同名的方法参数即可。

Spring MVC会自动进行类型转换

如果在控制单元方法参数中提供了参数。但是在请求中没有对应参数,这时Spring MVC会把null值赋予给参数。如果参数是关键字类型,是无法接收null值的,需要转换为Integer类型。在浏览器地址栏输入 http://localhost:8081/bjsxt/testParam?name=bjsxt 会出现异常  

2. @RequestParam 注解

 @RequestParam是方法参数级注解。每个控制单元方法参数前面都能写这个注解。在@RequestParam注解里面提供了四个属性,分别:

name、value、required、defaultValue、

(1)name:当请求参数名和控制单元参数名不对应时,可以使用name指定请求参数名。这样方法参数就可以不与请求参数对应了。

@RequestMapping("/testParam")
public String testParam(@RequestParam(name="name") String name123, Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

(2)value:是name属性的别名。功能和name属性相同。之所以再次设置一个和name属性相同的value,是因为在Java注解中,当需要设置value属性,且只需要设置value属性时可以省略value属性名,这样写起来更加简单。

@RequestMapping("/testParam")
public String testParam(@RequestParam("name") String name123, Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

(3)defaultValue:默认值。表示当请求参数中没有这个参数时给与的默认值。defaultValue类型是String类型,Spring MVC会对值进行类型转换,转换成参数类型。

@RequestMapping("/testParam")
public String testParam(@RequestParam("name") String name123,@RequestParam(defaultValue = "16") Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

(4)required:boolean类型,表示请求中是否必须包含参数。如果设置为true,且请求中没有这个参数,响应时出现400状态码。

@RequestMapping("/testParam")
public String testParam(@RequestParam("name") String name123,@RequestParam(required = true) Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

5.使用JavaBean作为参数(使用类对象作为控制单元参数)

 JavaBean:就是具体(非抽象)公共(public)的类,一个包含私有属性,getter/setter方法和无参构造方法Java类。是不是感觉和实体类特别像。其实写法上和实体类相同。唯一区别是实体类是数据库层面的概念,类型中属性要和数据库字段对应。而JavaBean的属性是灵活的,不是必须和哪里对应的。

JavaBean是一个专业概念,可以简单点理解:使用类对象做为控制单元参数,接收请求参数。如果不是特别较真,狭义上可以认为JavaBean就是项目中的实体类。

当使用类对象作为参数时,要求属性名和参数名对应,类型转换由Spring MVC自动完成。不支持@RequestParam注解。所以需要先建立一个类。且类中必须提供属性的getter和setter方法,因为Spring MVC就是通过getter和setter把请求参数的值设置到类的属性中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值