springMVC-2
SpringMVC框架
项目搭建流程
详见昨天笔记
请求参数传递及编码问题
SpringMVC框架可以丰常方便地接收用户的请求参数,而且也可以帮助我们自动封装成相应的对象
SpringMVC支持如下方式来获取用户的请求参数
- 直接在方法中,添加相关的实体类对象[PO, pojo]或是值对象[VO, Value Object]【比较常用】
//示例代码
@Controller
public class UserController {
@RequestMapping("/user/register")
/*****************
* 此处要求,页面表单项中的name属性值要和User对象的属性名保持一致,这个是约定
*/
public String register(User user,Model model) {
//...再做进一步的业务处理
}
}
- 直接在方法中,添加单个表单项的参数【比较常用】
//示例代码
@Controller
public class UserController {
@RequestMapping("/user/register")
/*****************
* 如果请求参数的名字与方法中的参数名不一样,我们有两种做法:
* 1. 修改方法中的参数名与页面表单项中的name属性值一样
* 2. 使用 @RequestParam 注解来修饰方法参数,使得名字与页面表单项中的name属性值一样
*/
public String login(String username, String pwd, Model model) {
//...再做进一步的业务处理
}
}
- 传统的代码,也就是原生的Servlet代码 【不可取,不建议使用】
//示例代码
@Controller
public class UserController {
@RequestMapping("/user/register")
public void register(HttpServletRequest req, HttpServletResponse resp) {
//通过req对象来获取用户的请求参数
String userName = req.getParameter("name");
String pwd = req.getParameter("password");
String realName = req.getParameter("realName");
//还要进一步封装
User user = new User();
user.setUserName(userName);
user.setPassword(pwd);
user.setRealName(realName);
//....再做进一步的业务处理
....
//绑定信息到request范围
req.setAttribute("key",xxxx);
//转发或重定向
String targetURL = "/jsp/xxx.jsp";
req.getRequestDispatcher(targetURL).forward(req,resp);
}
}
编码问题
为什么会有乱码?
数据的编码和解码不一致造成的。
在WEB应用中,请求的数据会根据method的类型不同,采用不同的位置来传输,如果是get请求,则数据封装到请求头[Header]中传输,如果是post请求,则数据封装到请求体部[body]传输
通过request.setCharacterEncoding方法,只能修改请求体部的编码,影响不了头部。
解决方案:
添加 编码过滤器, SpringMVC已经提供了一个编码过滤器
org.springframework.web.filter.CharacterEncodingFilter
,它只能影响POST请求在容器中,修改相关的配置项,以Tomcat为例,在
$CATALINA_HOME/conf/server.xml
中的标记中,增加一个 URIEncoding=“UTF-8” 属性。它会影响请求头的编码 如果你使用maven中Tomcat7插件的话,则只需要在 插件的配置中,添加一个属性:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8888</port>
<!-- 影响请求头的编码 -->
<uriEncoding>utf-8</uriEncoding>
</configuration>
</plugin>
注:以上的2 和 3本质是一样的。
静态资源访问
在SpringMVC提供的前置控制器[大C],它有如下的匹配模式
- 采用 *.xxx 来匹配,这种匹配模式叫扩展名匹配,它是基于后缀来匹配的,它的优点是不会拦截静态资源【像css, 图片,js之类的,只要大C的扩展名与静态资源扩展名不一样即可】,缺点是它不支持
Restful
风格的URL。- 采用 / 来匹配,这种匹配模式叫通配匹配,它可以匹配一切,优点完全支持
Restful
风格的URL,缺点是所有的静态资源也会被拦截,性能差一点。现在是主流【推荐】
如何在采用/匹配模式下,不让大C去拦截静态资源呢? 有如下三种方式:
- 利用容器本身的Servlet处理器,也叫默认处理器,在web.xml中,要配置在大C之前,如下:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
这种方式有两个缺点:
- 配置比较冗长,每一段servlet-mapping,只能处理一个扩展名
- 不同的WEB容器,这个默认的servlet-name是不一样的,如下:
- Tomcat 对应的是 default
- WebLogic 对应的是 FileServlet
- Websphere 对应的是 xxx [可以自已去查]
- Tomcat 对应的是 default
所以,不建议大家使用
- 在 xxx-servlet.xml 配置文件中,添加一个 配置,如下:
....
<mvc:default-servlet-handler/>
它会自动帮助我们选择一个默认的容器提供的 Servlet处理器
- 在 xxx-servlet.xml配置文件中,通过 <mvc:resources> 来添加静态资源
...
<mvc:resources mapping="" location=""/>
注:以上三种方式都是基于 xml
配置的,下面我们可以通过注解达到相同的目的
- 在
WebMvcConfig
配置类中,重写父类WebMvcConfigurerAdapter
中的addResourceHandlers
方法,如下:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
LOGGER.debug("--- 进入addResourceHandlers方法...");
//
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
}
注:此方法需要注意一点:
如果你的静态资源是放在 resources 目录下,则在addResourcelocations方法中,需要加上”classpath:” 前缀,如果放在 webapp目录下,则不需要添加 “classpath:” 前缀
- 在
WebMvcConfig
配置类中,重写父类WebMvcConfigurerAdapter
中的configureDefaultServletHandling
方法,如下:
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
LOGGER.debug("--- 进入configureDefaultServletHandling方法...");
configurer.enable();
}
注:相当于在xml中,添加了
<mvc:default-servlet-handler/>
建议:使用第一种方案
视图解析器的配置
默认情况下,没有指定视图解析器时,我们在控制器的方法中,需要编写完整的目标资源路径. 当然,我们也可以为项目配置一个视图解析器,方便我们的开发
注解的配置步骤:
- 在
WebMvcConfig
配置类中,添加一个 @Bean 方法,在这个方法中,创建一个InternalResourceViewResolver
对象,并设置相关的属性,如下:
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
//创建InternalResourceViewResolver
InternalResourceViewResolver irvr = new InternalResourceViewResolver();
//设置属性
irvr.setPrefix("/WEB-INF/jsp/"); //指定前缀
irvr.setSuffix(".jsp"); //指定后缀
//设置视图处理类 [可选,默认就是 JstlView.class ]
irvr.setViewClass(JstlView.class);
//
return irvr;
}
- 然后,在你的控制器的方法中,直接返回 目标jsp文件的名字即可,无需使用 全路径。
有关转发和重定向
有SpringMVC框架中,我们同样可以指定请求是转发[forward]还是重定向[redirect], 方法如下:
在 控制器方法的返回字符中中,添加两个前缀:
- forward: 表示 转发,默认就是这个, 但是,我们在返回值中,加与没有加 forward前缀是有很大差别的,如果加了 forward: 前缀,则会无视配置的视图解析器
- redirect: 表示重定向