学习SpringMVC框架的简单使用
1. 初识SpringMVC,了解简易的实现流程,快速实现
1.1. 所有的请求都经过前端调度器(DispatcherServlet),需要在web.xml中配置,设置所有的请求都通过 /
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 前端调度器 -->
<servlet>
<servlet-name>Allin</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 设置读取配置文件的位置 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Springmvc-beans.xml</param-value>
</init-param>
<!-- 设置tomcat服务器启动就开启 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Allin</servlet-name>
<!-- / 表示匹配所有请求,但不包括 .jsp的 -->
<!-- /* 表示匹配所有请求,包括 .jsp的 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
1.2. 配置上面的配置文件,设置映射处理器,处理适配器,视图解析器,处理器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
">
<!-- 映射处理器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- http://localhost/hello -->
<!-- 处理器 根据上面选的映射器,这里需要设置的id为url的路径 /hello -->
<bean id="/hello" class="com.xxx.controller.controllerTest"/>
</beans>
// 处理器,实现Controller接口
package com.xxx.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class controllerTest implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("mess","哈哈哈哈哈哈"); // 传递参数给视图
mv.setViewName("showHello"); // 视图解析器会将此解析为 /WEB-INF/jsp/showHello.jsp
System.out.println("===================================");
return mv;
}
}
1.3.maven的依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.18.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<!--JSTL表达式依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
1.4. 如果报404的错误,可能是没有在tomcat中导出jar包
解决方式: 在 Artifacts的界面新建一个lib文件夹,在导入所有的jar包,点击Apply,最后点击OK,重启Tomcat服务器试试
2. 使用注解形式的映射器和适配器简化代码
2.1. 第一步 还是配置web.xml的前端调度器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 前端调度器 -->
<servlet>
<servlet-name>Allin</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 设置读取配置文件的位置 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Springmvc-beans.xml</param-value>
</init-param>
<!-- 设置tomcat服务器启动就开启 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Allin</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.2. 第二步配置前端控制器读取的Springmvc-beans.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 使用注解形式的的映射处理器和处理器适配器 @RequestMapping -->
<mvc:annotation-driven/>
<!-- 让静态资源过滤,不进行视图解析器的处理 如:.css/.js/.jpg 等的资源-->
<mvc:default-servlet-handler/>
<!-- 扫描包,注册控制器(处理器)@Controller -->
<context:component-scan base-package="com.xxx.controller"/>
<!-- 视图解析器 "test01" ====》/WEB-INF/jsp/test01.jsp -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
2.3. 第三步编写处理器,使用注解进行配置
// 被扫描注册Bean
@Controller
public class HelloTest {
// 进行url的映射配置 http://localhost/show01
@RequestMapping("/show01")
public String show01(Model model){
// model为传递给视图的数据
model.addAttribute("msg","hello springmvc");
// 返回的字符串 会进行视图解析器的处理 返回该路径下的jsp:/WEB-INF/jsp/test01.jsp
return "test01";
}
}
3. @Contorller 和 @RequestMapping
3.1. @Contorller
使用@Controller相当于实现Controller的接口,表示该类是一个处理器类,并且可以被包扫描直接注册到Spring容器中
3.2. @RequestMapping
@RequestMapping相当于之前写在Bean的id,是映射处理器找到该方法的凭据
@RequestMapping 可以同时加在类上和方法上,到时候访问该方法就是类上的加上方法上的
@Controller
@RequestMapping("/test01")
public class TestController {
@RequestMapping("/show01") // 路径为/test01/show01
public String show01(){
System.out.println(123);
return "test";
}
}
4. RestFul风格
https://blog.csdn.net/qq_27026603/article/details/82012277
4.1. 传递的参数位置不同(使用注解@PathVariable进行url参数的映射)
原来的请求: http://localhost:8080/hello?a=7&b=25
RestFul 风格: http://localhost:8080/hello/7/25
这是明显的形式,RestFul风格将参数写在url地址中,不进行参数的携带
@Controller
public class TestController {
@RequestMapping("/show01/{data1}/{data2}")
public String show01(@PathVariable("data1") String a, @PathVariable("data2") String data2,Model model){
System.out.println(a);
System.out.println(data2);
model.addAttribute("msg",a+data2);
return "test";
}
}
4.2. 请求方式不同 ,操作不同(相同的url,用不同的请求方式代表不同的操作)
**RestFul风格可以通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行不同的操作。**其中,GET 用于查询资源,POST 用于创建资源,PUT 用于更新服务端的资源的全部信息,PATCH 用于更新服务端的资源的部分信息,DELETE 用于删除服务端的资源。
传统方式操作资源 :
http://127.0.0.1/item/queryUser?id=1 查询,GET
http://127.0.0.1/item/saveUser 新增,POST
http://127.0.0.1/item/updateUser 更新,POST
http://127.0.0.1/item/deleteUser?id=1 删除,GET或POST
RestFul风格: 可以实现url 相同,请求的映射和响应不同
http://127.0.0.1/item/item/1 get 方式查询
http://127.0.0.1/item/item post方式新增
http://127.0.0.1/item/item put方式更新
http://127.0.0.1/item/1 delete方式删除
4.3. java代码展示
@Controller
public class TestController {
// 指定 只有Post请求才能访问 还可以使用简化版的mapping
@RequestMapping(value = "/show01/{data1}/{data2}",method = RequestMethod.POST)
// 这两个效果等价 method的参数 GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE;
// @PostMapping("/show01/{data1}/{data2}")
public String show01(@PathVariable("data1") String a, @PathVariable("data2") String data2,Model model){
System.out.println(a);
System.out.println(data2);
model.addAttribute("msg",a+data2);
return "test";
}
}
继续使用get请求去访问会报错
5. 转发和重定向
5.1. 使用最原始的Request的转发和Response的重定向(不需要视图解析器)
转发
@Controller
public class Test02Contro {
@RequestMapping("/t2")
// 直接使用原始的request , response 参数操作
public void test02(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("msg", "t2");
// 不能视图解析器需要自己指定 完整的访问路径
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
}
重定向
@RequestMapping("/t3")
public void test03(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 重定向不能使用request传递参数,因为不是同一个request请求,这里使用session进行传参
req.getSession().setAttribute("msg","Test02/t3");
// 用户不能访问WEB-INF下的资源,所以show.jsp直接在webapp目录中
resp.sendRedirect("/show.jsp");
}
5.2. 不定义视图解析器实现转发和重定向
转发(使用forward:或者默认为转发)
@RequestMapping("/h1")
public String h1(Model model){
model.addAttribute("msg","/h1");
return "forward:/WEB-INF/jsp/test.jsp";
}
// ============forward:可以省略 , 默认是转发=====================
@RequestMapping("/h1")
public String h1(Model model){
model.addAttribute("msg","/h1");
return "/WEB-INF/jsp/test.jsp";
}
重定向 (使用redirect: 表示重定向 )
@RequestMapping("/h2")
public String h2(Model model){
// 重定向时: 这里的model 传递形式为 url 后面 http://localhost/show.jsp?msg=%2Fh2
model.addAttribute("msg","/h2");
return "redirect:/show.jsp";
}
// jsp使用param.参数名 读取
${param.msg}
5.3. 定义视图解析器实现转发和重定向
转发
@RequestMapping("/forwar")
public String forwar(Model model){
model.addAttribute("msg", "forwar test04");
return "test"; // 会进行拼接 /WEB-INF/jsp/test.jsp
}
重定向
@RequestMapping("/redi")
public String redi(Model model){
model.addAttribute("msg", "redi test04");
return "redirect:/show.jsp"; // 重定向使用redirect:全路径(不会进行视图解析器的拼接) 所以有没有视图解析器重定向不变
}
6. 数据接收和数据回写
6.1. 接收数据,例如:http://localhost/form/show1?name=xxx&password=123
// 前端传递的参数名和这里的参数名一样,springmvc会自动进行匹配
@RequestMapping("/form/show1")
public String show1(String name,String password, Model model) throws UnsupportedEncodingException {
model.addAttribute("user", name);
model.addAttribute("pwd", password);
return "test";
}
// ================前端传递的参数名和这里的参数名不一样,需要使用@RequestParam("前端的参数名")进行映射================
@RequestMapping("/form/show1")
public String show1(@RequestParam("name") String user,@RequestParam("password") String pwd, Model model) throws UnsupportedEncodingException {
model.addAttribute("user", user);
model.addAttribute("pwd", pwd);
return "test";
}
注:使用了@RequestParam(“name”)就必须进行参数的传递,否则会报错,不使用这个不传参则默认为null
6.2. 乱码问题
建议使用springMVC自带的乱码过滤器
<filter>
<filter-name>encodingCharacter</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>encodingCharacter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6.3. JSON
6.3.1 返回字符串数据,不进行视图解析器处理
- 使用 @Controller + @ResponseBody
@Controller
public class jsonController {
@ResponseBody
// produces = "text/html;charset=utf-8" 表示返回的类型 相当于原始的 contextType
@RequestMapping(value = "/abc",produces = "text/html;charset=utf-8")
public String test01(){
return "奥迪";
}
- 使用 @RestController 等价于上面
// 表示该类的方法返回的都是字符串
@RestController
public class jsonController {
// 设置编码类型为utf-8,防止乱码
@RequestMapping(value = "/abc",produces = "text/html;charset=utf-8")
public String test01(){
return "奥迪";
}
6.3.2 JSON
json只是一种数据传输的格式,在前端方便使用 JavaScript 解析(是JavaScript的一个对象),格式为 {“aa”:“aaa”,“bb”:“bbb”},多个对象使用[]括起来 , [{},{},{}…]
6.3.3 使用第三方的fastjson可以快速将对象解析为json格式的字符串,maven依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.66</version>
</dependency>
6.3.4 java代码
import com.alibaba.fastjson.JSON;
import com.xxx.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@Controller
//@RestController
public class jsonController {
@ResponseBody
// 设置传输的类型为json
@RequestMapping(value = "/abc4",produces = "application/json;charset=utf-8")
public String test04(){
User user1 = new User("小星星1", 12, "男");
// 使用fastjson的工具类进行转换
String str = JSON.toJSONString(user1);
return str;
}
@ResponseBody
@RequestMapping(value = "/abc5",produces = "application/json;charset=utf-8")
public String test05(){
User user1 = new User("小星星1", 12, "男");
User user2 = new User("小星星2", 12, "男");
User user3 = new User("小星星3", 12, "男");
User user4 = new User("小星星4", 12, "男");
List<User> uls = new ArrayList<User>();
uls.add(user1);
uls.add(user2);
uls.add(user3);
uls.add(user4);
String str = JSON.toJSONString(uls);
return str;
}
}
这个配置可以替换 produces = “text/html;charset=utf-8” 返回的字符串不会乱码
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg ref="utf8Charset"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="utf8Charset" class="java.nio.charset.Charset" factory-method="forName">
<constructor-arg value="UTF-8"/>
</bean>