回顾Servlet
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>hello</servlet-name>
<servlet-class>com.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Test</title>
</head>
<body>
${msg}
</body>
</html>
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
req.getSession().setAttribute("msg", "执行" + method + "了方法");
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
回顾MVC
MVC框架做的事情:
1将url映射到java类或java类方法
2封装用户提交的数据
3处理请求-调用相关的业务处理-封装响应数据
4将响应的数据进行填充 .jsp .html等表示层数据
SpringMVC
三大件
处理器映射器,处理器适配器,视图解析器
dispacher拦截所有请求,交给处理器映射,再执行返回dispatcher,再通过处理适配器交给Controller,执行完返回结果到视图处理,之后返回给前端。
依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
下面不是主要依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
配置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">
<!--注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--/匹配所有请求(不包括jsp,/*包括)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置resources下的springmvc-servlet.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--处理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 视图解析器配置(最普遍通用视图解析器) -->
<!--1获取ModelAndView中的数据;2解析其中的视图名;3拼接视图名找到对应视图;4将数据写进视图-->
<bean id="InternalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--jsp文件所在的包名前缀 -->
<property name="prefix" value="/WEB-INF/jsps/"></property>
<!--jsp文件的后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
<bean id="/hello" class="com.controller.HelloController"/>
<!--注意访问名称前有斜杠,不然会报错-->
配置Controller
package com.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author: 1298509345
* date: 2020/4/7
* Time: 16:32
*/
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
//创建模型视图对象
ModelAndView mv = new ModelAndView();
//封装对象
mv.addObject("msg", "HelloSpringMVC");
//封装要跳转的视图,放在mv中,WEB-INF/jsp/hello.jsp
mv.setViewName("hello");
return mv;
}
}
注解配置文件
web.xml跟之前相同。
springmvc-servlet.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="com.controller"/>
<!--让springmvc不处理静态资源-->
<mvc:default-servlet-handler/>
<!--mvc注解驱动-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--解析视图前缀后缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
Controller类
@Controller//被Controller注解的类中的所有方法返回值为String且有具体页面可以跳转的就会被视图解析器解析
//@RequestMapping("h")
public class HelloController {
/**
* 如果类上还有RequestMapping,会有一个层级关系,如h/hello
*/
@RequestMapping("/hello")
public String hello(Model model) {
//封装数据
model.addAttribute("msg", "helloSpringMVC");
//会被视图解析器处理
return "hello";
}
}
流程
1 .web项目
2.依赖(jar包)
3.web.xml 注册DispatcherServlet
4.springmvc配置文件
5.Controller
6.视图(jsp,html)和controller对应
7.运行
注解
不同层的注解,但效果一样
@Component
@Service service
@Controller Controller
@Repository Dao
Restful风格
@Controller
public class RestfulController {
//之前的方式http://localhost:8080/springmvc_3_war_exploded/add?a=1&b=3
//Restful:http://localhost:8080/springmvc_3_war_exploded/add/a=1/b=3
//questMapping(name = "/add/{a}/{b}",method = RequestMethod.DELETE)
@GetMapping("/add/{a}/{b}")每个方法都有对应的变体
public String test1(@PathVariable int a,@PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg", res);
return "test";
}
}
显式定义用name可能会有错,应当用value或者path
//Restful风格可通过相同url使用不同方法,如下get和post访问路径相同,可通过表单调用post方法
//之前的方式http://localhost:8080/springmvc_3_war_exploded/add?a=1&b=3
//Restful:http://localhost:8080/springmvc_3_war_exploded/add/1/3
// @RequestMapping(name = "/add/{a}/{b}",method = RequestMethod.DELETE)
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg", res);
return "test";
}
@PostMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg","测试2"+ res);
return "test";
}
@GetMapping("/a")
public String fun_a(){
return "a";
}
//jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/add/1/2" method="post">
<input type="submit">
</form>
</body>
</html>
//如果有两个相同的路径会报错
@RequestMapping(value = "/add/{a}/{b}")
public String test0(@PathVariable int a, @PathVariable int b, Model model) {
model.addAttribute("msg", a + b);
return "test";
}
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg", res);
return "test";
}
不明确的方法
所以尽量使用方法的细致Mapping,不用RequestMapping
SpringMVC结果跳转方式
类Servlet转发的方式,没有视图解析器。
@GetMapping("/m1/h1")
public String test(Model model){
//转发方式
model.addAttribute("msg","ModelTest1");
return "/WEB-INF/jsp/test.jsp";
}
@GetMapping("/m1/h1")
public String test(Model model){
//重定向方式
model.addAttribute("msg","ModelTest1");
return "redirect:/index.jsp";
}
配置了视图解析器只需要返回页面名称,如果要重定向亦然可以添加redirect完成
前后端传参数
//访问路径http://localhost:8080/user/t1?name=qingj//前后端名称须一致
@RequestMapping("/user")
public class UserController {
@GetMapping("/t1")
public String test1(String name, Model model){
//接受前端参数
System.out.println("接到参数为"+name);
//返回结果给前端
model.addAttribute("msg",name);
//视图跳转
return "test";
}
}
如果要确定参数名称可通过下,显式定义名称
public String test1(@RequestParam("username") String name, Model model)
若传参为对象类型,访问路径的参数必须与对象字段名称一致
//http://localhost:8080/user/t2?name=syg&id=1&age=1
public class User {
private int id;
private String name;
private int age;
}
Model
中文乱码问题
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/e/t1" method="post">
<input type="text"name="name">
<input type="submit">
</form>
</body>
</html>
<!--表达提交汉字可能会出现乱码,解决方式过滤器-->
//手动过滤器
public class EncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
filterChain.doFilter(request,response);
}
public void destroy() {
}
}
xml文件中配置过滤器
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
以上这种方式可能还会出现乱码,解决方法,web.xml中添加spring的过滤器
<filter>
<filter-name>encoding</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>encoding</filter-name>
这里路径有没有星号也有可能是乱码原因
<url-pattern>/*</url-pattern>
</filter-mapping>
JSON
NoClassDefFoundError
启动服务器时没在web-inf文件夹下的lib添加所需的包
添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
@Controller
public class UserController {
//ResponseBody不会走视图解析器,也可设置RestController,使其只返回字符串
//设置编码解决乱码问题
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
@ResponseBody
public String json1() throws JsonProcessingException {
ObjectMapper mapper=new ObjectMapper();
User user=new User(3,"八重樱","女");
对象转为字符串
String s = mapper.writeValueAsString(user);
return s;
}
}
统一解决方案:spring中有现成的方法避免乱码,修改注解驱动
<!--mvc注解驱动-->
<mvc:annotation-driven>
<!--JSON乱码问题解决-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
传集合类型
@RequestMapping("/j2")
@ResponseBody
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<User> users = new ArrayList<User>(3);
User user = new User(3, "八重樱1", "女");
User user2 = new User(3, "八重樱2", "女");
User user3 = new User(3, "八重樱3", "女");
users.add(user);
users.add(user2);
users.add(user3);
String s = mapper.writeValueAsString(users);
return s;
}