目录
基础
三层框架中的web层
mvc架构
- 前端控制器(DispatcherServlet):流程控制的中心,管理其他组件
- 处理器映射器(HandlerMapping):(RequestMapping)根据用户请求找到Handler(control方法)
- 处理器适配器:
- 处理器:controller方法
- 视图解析器:根据逻辑地址找到物理地址,解析并渲染提交页面
mvc加载流程
- tomcat启动,加载web.xml
- 过滤器:解决post乱码问题
- 前端控制器:加载核心配置文件,处理所有请求
- 加载springmvc.xml
- 包扫描
- 配置注解驱动,创建springmvc容器:转换器、视图解析器、静态资源
mvc请求流程
- HTTP请求到前端控制器
- 前端控制器根据requestmapper寻找并执行方法
- 根据返回值,提交到视图解析器
- 视图解析器返回页面
mvc编写流程
和加载流程一致,便于理解
配置maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--本案例使用Tomcat进行部署,Tomcat自己有servlet-api的包,需要部署的时候排出这个包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--本案例使用Tomcat进行部署,Tomcat自己有jsp-api的包,需要部署的时候排出这个包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
</dependency>
配置web.xml
解决post中文乱码
配置前端控制器(DispatcherServlet)
<!--配置过滤器解决post的乱码问题-->
<filter>
<!--给过滤器起名,叫啥都行-->
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--指定过滤器的编码为UTF-8-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--设置乱码解决的过滤器使用-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!--配置过滤器的映射,什么请求使用这个过滤器.本例就是所有请求/*-->
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--配置加载SpringMVC的核心配置文件-->
<!--contextConfigLocation:是固定写法,是springMVC的属性,不能改-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--配置在什么时候启动SpringMVC容器-->
<!--使用这种方式:当配置的值是大于0的正整数的时候,SpringMVC是随着Servlet容器(Tomcat)的启动而启动-->
<!--如果为0或者这不进行配置,SpringMVC的容器是用户第一次访问的时候启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<!-- 所有的请求都会被Servlet处理 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
配置springmvc.xml
包扫描
配置注解驱动-转换器-视图解析器
<!--包扫描-->
<context:component-scan base-package="com.alvin.controller"/>
<!--配置注解驱动-->
<!--配置转换器-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--配置转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.alvin.converter.DateConverter"/>
</set>
</property>
</bean>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--解决css静态资源的问题-->
<mvc:resources mapping="/css/**" location="/css/"/>
转换器示例代码
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String,Date> {
@Override
public Date convert(String s) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = dateFormat.parse(s);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
编写control
@Controller
@RequestMapping("alvin")//所有方法映射的url要加上value
public class HelloController {
//可以只写路径,method默认get,参数默认任意
//如果后面写参数,则参数必须一致,否则报错
@RequestMapping(value = "/hello",method = RequestMethod.GET,params = {"id","money>100"})
public String hello() {
System.out.println("入门案例,执行到这里了");
//返回xml里面指定的jsp
return "success";
}
}
编写web请求页面
可以提交基本类型,数组、map、pojo
<form action="/user/getUser" method="post">
<input name="id" value="1"/>
<input name="name" value="李白"/>
<input name="accounts[0].id" value="0" />
<input name="accounts[0].money" value="99999" />
<input name="accounts[1].id" value="0"/>
<input name="accounts[1].money" value="99999"/>
<input name="map[nihao].id" value="1"/>
<input name="map[nihao].money" value="111111"/>
<input type="submit" value="post提交"/>
</form>
标题二
modelAttribute
在请求执行之前执行的方法
# 基础使用
@ModelAttribute
public void modelAttribute(Person person) {
System.out.println(person.getUsername() + "model");
}
@RequestMapping("test")
public String test(Person person) {
System.out.println(person.getUsername());
return "success";
}
# 返回对象
//返回的值会保存在容器中
@ModelAttribute
public Person methodAttribute(){
Person person = queryPerson();
return person;
}
# 自定义存储名称
@ModelAttribute
public void methodAttribute(Map<String,Person> map){
Person person = queryPerson();
map.put("abc", person);
}
@RequestMapping("test")
public String test(@ModelAttribute("abc") Person person) {
System.out.println(person);
return "success";
}
sessionAttribute
@Controller
@SessionAttributes(value = {"username", "password"}, types = Integer.class)
@RequestMapping("sessionAttribute")
public class SessionAttributeController {
@RequestMapping("put")
public String putTest(Model model) {
model.addAttribute("username", "李白");
model.addAttribute("password", "123456");
model.addAttribute("age", 123);
model.addAttribute("addr", "addr");
return "success";
}
@RequestMapping("get")
public String getTest(ModelMap map) {
System.out.println(map.get("username"));
System.out.println(map.get("password"));
System.out.println(map.get("age"));
System.out.println(map.get("addr"));//不会输出
return "success";
}
@RequestMapping("clean")
public String cleanTest(SessionStatus sessionStatus) {
sessionStatus.setComplete();
return "success";
}
}
restful
增post 删delete 查get 改put
- 添加put、delete等请求的支持
<!--支持put、delete等请求-->
<filter>
<filter-name>methodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<!--必须放在解决乱码的前面-->
<filter-mapping>
<filter-name>methodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 前端post请求必须包含_method:put,后端代码:
@RequestMapping(value = "person/{id}", method = RequestMethod.PUT)
@ResponseBody //返回的是普通数据
public String update(@PathVariable("id") int id) {
System.out.println(id);
return "success";
}
返回值
- 返回string
默认会返回给视图解析器
可以通过@ResponseBody返回普通数据
- 返回void
本质就是使用request和response
- 返回ModelAndView
@RequestMapping("modelAndView")
public ModelAndView modelAndView() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("success");
modelAndView.addObject("username", "李白");
return modelAndView;
}
转发和重定向
@RequestMapping("testForward")
public String testForward(){
//使用forward关键词完成请求转发,到success.jsp成功页
return "forward:/WEB-INF/jsp/success.jsp";
}
@RequestMapping("testRedirect")
public String testRedirect(){
//使用redirect关键词完成请求重定向,到第一个testString方法
return "redirect:testString";
}
json
请求必须是json!!!JSON.stringify(rowData)
- 应用
<!--支持json格式数据交互的依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
- 使用
public @ResponseBody Person test(@RequestBody() Person person) {
return person;
}
文件上传
- 引入
<!--支持文件上传的组件-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!--跨服务器文件上传的支持-->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
- 配置文件解析器
<!--配置文件上传解析器-->
<!--上传解析器的id必须是接口名,首字母消息-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--配置上传文件的大小不能超过1M-->
<property name="maxUploadSize" value="1048576"/>
</bean>
- 使用
# 上传到本地服务器
public String upload(MultipartFile uploadFile, String fileName) throws IOException {
uploadFile.transferTo(new File("D:/alvin/1.jpg"));
//返回成功页面
return "success";
}
# 上传到其他服务器
# 修改要上传服务器tomcat的web.xml
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
------------------------------------
String imageUrl = "http://127.0.0.1:9090/uploads/"
//使用jersey进行上传
Client client = Client.create();
//执行上传的路径
WebResource resource = client.resource(imageUrl + fileName);
//执行上传
resource.put(String.class,uploadFile.getBytes());
异常处理
- 自定义error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
自定义异常!!!
</body>
</html>
- 自定义异常
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
- 自定义全局异常
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyHandleExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
MyException myException = null;
if (ex instanceof MyException) {
myException = (MyException) ex;
} else {
myException = new MyException("运行异常,请找管理员");
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", myException.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
- 配置全局异常处理器(springmvc.xml)
<!--全局异常处理-->
<bean class="com.alvin.ex.MyHandleExceptionResolver"/>
- 正常使用即可
int a = 1 / 0;
Interceptor拦截器
与filter区别:
interceptor只能springmvc使用,filter属于servlet;
interceptor只能拦截方法,filter可以拦截所有。
- 自定义拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("posthandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("after");
}
}
- 注册
springmvc.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test/**"/>
<bean class="com.alvin.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>