环境搭建
1.new->Moudule(选project当然也可以)
2.选择1.8不要用默认的
说明:如果你是new project直接是1.8不需要多余选择
3.在最后添加一个键值对for Maven项目的快速构建
4.项目结构:(补全目录结构)
Maven项目的目录结构是固定的。在main下创建一个java(用于写类)和一个resources目录(用于存放配置文件)。
还没完需要给java目录设置成源码的根目录,resources设置成资源的根目录。
4.1 删除默认的index.jsp
删除默认的,然后自己再新建一个。因为默认的没有支持中文那些模版设置。
5.导入Jar包(pom.xml)
略。
6.配置前段控制器:
配置前端控制器,其实就是一个Servlet。如果是一个Servlet肯定在web.xml里去配置。
这个类是Spring提供好了的一个类,刚才已经导入过对应的Jar包了,这个类就可以直接去用。
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
拦截写:/
<url-pattern>/</url-pattern>
说明:表示你发任何一个请求都会经过这个Servlet。
7.编写springmvc.xml
8.配置服务器
在配置好Deploment之后记得回来设置Server的Redeploy这部很关键,以后就不需要每次restart了。
9.开启注解扫描
在springmvc.xml配置文件中
<!--配置spring创建容器时要扫描的包-->
<context:component-scan base-package="com.jtl"></context:component-scan>
10.加载springmvc.xml配置文件
在web.xml前端控制器(Servlet)中去加载。提供一组全局的初始化参数。
说明:给DispatcherServlet这个类的contextConfigLocation这个属性传个值:classpath:springmvc.xml。
再加一个配置:
说明:Servlet这个类正常来讲,是在你第一次发请求的时候创建。但配置了<load-on-startup>之后,以后启动服务器就会创建DispatcherServlet这个对象,Servlet一旦创建就会帮你加载springmvc.xml这个配置文件。springmvc.xml一加载,扫描就生效了。Controller类就会被扫描到,它就会变成对象,里面的方法也就会生效。【这一步很关键,虽然不用配置load-on-startup程序也能正常运行,但是这个逻辑是不一样的,一个是在请求的时候才创建Servlet对象这样子会使响应速度变慢】
11.配置视图解析器
<!-- 配置视图解析器对象 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
12.开启SpringMVC框架注解的支持
<mvc:annotation-driven/>
在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器成为SpringMVC的三大组件。使用<mvc:annotation-driven/>自动加载RequestMappingHandlerMapping(处理映射器)和RequestMappingHandlerAdapter ( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用 <mvc:annotation-driven>替代注解处理器和适配器的配置。
注意:一般开发中,我们都需要写上此标签(虽然从入门案例中看,我们不写也行,随着课程的深入,该标签还有具体的使用场景)。
明确:我们只需要编写处理具体业务的控制器以及视图。
其他:
RequestMapping请求参数:
value和method比较常用,params和headers很少用。path与value的作用相同,查看源码可以知道它们都有个@AliasFor别名注解,分别指向对方。当只有一个value属性时,可以省略属性名value直接写"??"。
易错点:
相对路径写法:请求时会自动加上项目描述:
<%--注意:前面不加/是相对路径的写法--%>
<a href="user/testRequestMapping">RequestMapping注解</a>
如果写成:这是绝对路径的写法,则不会加上会报404:
<a href="/user/testRequestMapping">RequestMapping注解</a>
3.请求参数的绑定
当方法的名字与表单提交的名称是一模一样的,mvc这个框架会自动的把你传的值赋值到方法的参数上,这就是请求参数的绑定。底层的做法是,通过反射的方式,拿到这个方法的属性,然后把表单名字传给属性的值。
配置解决中文乱码的过滤器
get请求不会出现中文乱码问题,post请求会出现。解决方式:request.setCharacterEncoding("UTF-8"),在Controller每次去设置这个东西,但这样做太麻烦。SpringMVC框架给我们提供了一个过滤器,你发任何请求过滤器都可以拦截你,过滤器把你拦到,帮你解决中文乱码问题。
在web.xml中配置:
<!--配置解决中文乱码的过滤器-->
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
HttpServletRequest不需要写全
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("execute testServlet...");
System.out.println(req);
HttpSession session = req.getSession();
System.out.println(session);
ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);
System.out.println(resp);
return "success";
}
说明:这个方法的两个参数是为了绑定request对象和response对象。但是不需要将req写全request对象的名字一模一样也能绑定成功。我的理解是,每次请求只会有一个HttpServletRequest对象,所以方法的类型写对了,那么就可以成功绑定赋值,不像其他String字符串必须名称一一对应,个人理解可能不对,望指出。
第4章 常用注解
4.1 RequestParam
前段代码
<a href="anno/testRequestParam?name=JTL">RequestParam</a><br>
后端代码
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(name = "name") String username) {
System.out.println("execute testRequestParam...");
System.out.println(username);
return "success";
}
说明:@RequestParam这个注解中的name和value属性是等价的,且还有一个属性叫作required属性,默认为true,意为:必须的意思。就是说前面必须得穿一个名叫name的参数过来,换成其他的都不可以了,username当然也不行。必须传name过来,当时你也可以手动设置为false。
4.2 RequestBody
get请求不是用,因为get方式是没有请求体的,它把请求的参数都封装到了地址栏上。post才有请求体这个内容。
作用场景:异步,异步传的是Json数据,传Json数据需要给对象封装。
前端:发送一个post请求。
后端:public String testRequestBody(@RequestBody String body) {}就可以拿到RequestBody。
4.3 PathVariable
restful风格优点:缓存很好维护,请求路径都是一个,这些缓存都存在一个文件中就可以了,利于管理。同样的请求路径,但是会通过不用的请求方法区分调用Controller中的哪个方法;url支持占位符是spring3.0之后加入的,是springmvc支持restful风格url的一个重要标志。
前端:<a href="anno/testPathVariable/7">testPathVariable</a>
后端:
@RequestMapping("/testPathVariable/{pid}")
public String testPathVariable(@PathVariable(name = "pid") String id) {
System.out.println("execute testPathVariable...");
System.out.println(id);
return "success";
}
4.3.4 HiddenHttpMethodFilter过滤器
WebClient 这个类也可以干这些事(发送PUT、DELETE请求等)。可以直接使用静态方法发送请求,模拟各种请求方式。这种方式很简单,不用写任何配置文件,直接调用这个类的静态方法。
用浏览器来发PUT请求也是可以的,可以装插件模拟各种请求。
4.4 RequestHeader
用处不大。在实际开发中一般不怎么用。
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept") String header) {
System.out.println("execute testRequestHeader...");
System.out.println(header);
return "success";
}
4.5 CookieValue
在实际开发中也不怎么用。
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookieValue) {
System.out.println("execute testCookieValue...");
System.out.println(cookieValue);
return "success";
}
说明:当前发起一个请求,服务器端会创建一个session对象,然后它会通过cookie的形式把session给你写回来,名字叫作:JSESSIONID。
4.6 ModelAttribute
应用场景:当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
方式1:带返回值的
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("execute testModelAttribute...");
System.out.println(user);
return "success";
}
@ModelAttribute
public User showUser(String uname) {
System.out.println("execute showUser...");
//通过用户名查询数据库(模拟)
User user = new User();
user.setUname("jtl");
user.setAge(20);
user.setDate(new Date());
return user;
}
方式2:不带返回值
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("u") User user) {
System.out.println("execute testModelAttribute...");
System.out.println(user);
return "success";
}
@ModelAttribute
public void showUser(String uname, Map<String, User> map) {
System.out.println("execute showUser...");
//通过用户名查询数据库(模拟)
User user = new User();
user.setUname("jtl");
user.setAge(20);
user.setDate(new Date());
map.put("u", user);
}
4.7 SessionAttribute
作用:用于多次执行控制器方法间的参数共享。
测试需要:在request域对象中存一个值,然后再success.jsp界面来取得这个值,可以用用原生Servlet的API来实现。这么做没有任何的问题,但是有缺陷:很耦合,和ServletAIP有了过于高的耦合。这样做开发很不好,如果你没有Servlet这个API的话,那你的程序在编译器都会报错的(没有这个Jar包编译不了)。SpringMVC为了解决这个耦合,帮我们提供了一些类帮我们去操作,Model。向Model里面去存东西,其实它底层会把数据存入到request这个域对象中。
1)用ServletAPI
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(HttpServletRequest req) {
System.out.println("execute testSessionAttributes...");
req.setAttribute("name","jtl");
return "success";
}
2)用Model类
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model) {
System.out.println("execute testSessionAttributes...");
//底层会存储到request域对象中,以后再也不用写request
model.addAttribute("msg","JTL");
return "success";
}
3)不同方法间的参数共享
@RequestMapping("/getSessionAttributes")
public String getSessionAttributes(ModelMap modelMap) {
System.out.println("execute getSessionAttributes...");
//这里不能用Moder因为它是个接口没有get方法,真正运行的肯定是它的实现类ModelMap
String msg = (String) modelMap.get("msg");
System.out.println(msg);
return "success";
}
4)不同方法间的参数共享
@RequestMapping("/delSessionAttributes")
public String delSessionAttributes(SessionStatus status) {
System.out.println("execute delSessionAttributes...");
//重置session对象
status.setComplete();
return "success";
}
注意:类上得有@SessionAttributes注解