springmvc-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.lcy.controller"/>
<mvc:default-servlet-handler/>
<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>
<mvc:annotation-driven>
<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>
beans>
web.xml
<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>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-app>
模型:Model(Dao/Service)
视图:view (jsp/html)
控制器:Controller(Servlet)
扩展:vo是实体类的一个细分,当我一个User类有20个字段,但我只需要做一个登陆功能,前端只需要用户名和密码,这个时候可以拆分出一个vo实体类,过滤一些不必要的东西。
1.将url映射到Java类或Java类的方法java
2.封装用户的提交数据
3.处理请求----调用相关的业务处理----封装响应数据
4.将响应的数据进行渲染.jsp/html等表示层数据
<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>srpingmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>srpingmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
<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">
web-app>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放到ModelAndView中
mv.addObject("msg","HelloSpringMvc");
//封装要跳转的视图,放到ModelAndView中
mv.setViewName("hello"); //:/WEB-INF/jsp/hello.jsp
return mv;
}
}
DispatchedServlet接收请求并拦截请求。
我们假设请求的url为:http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080 指的是服务器域名
SpringMVC 是指部署在服务器上的web站点
hello 表示控制器
如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
//RestFul:http://localhost:8080/mvc/add/a/b
@RequestMapping("/add/{a}/{b}")
public String text01(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg","结果是:"+res);
return "addPage";
}
没有使用RestFul
//原来的:http://localhost:8080/mvc/add?a=1&b=2
@RequestMapping("/add")
public String text01(int a, int b, Model model) {
int res = a + b;
model.addAttribute("msg","结果是:"+res);
return "addPage";
}
使用指定的方式 地址请求栏默认都是HTTP GET
// @RequestMapping(value = "/add/{a}/{name}",method = RequestMethod.GET)
@PostMapping("/add/{a}/{name}")
public String text01(@PathVariable int a, @PathVariable String name, Model model) {
String res = name +a;
model.addAttribute("msg","结果1是:"+res);
return "addPage";
}
简洁:风格简单
安全:隐藏了程序里面的一些东西,比如参数等
高效:支持缓存
这个数据要从前端接收的加上@RequestParam注解,避免很多无用的请求。高效
//2.提交的域名称和处理方法的参数名不一样
@GetMapping("/t1")
public String test01(@RequestParam("username")String name, Model model) {
//1.接收前端参数
System.out.println("前端的参数为:"+name);
//2.将返回的结果传递给前端
model.addAttribute("msg",name);
//3.跳转视图
return "hello";
}
要求前端传递的参数名和对象名必须一致,否则就是null
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
控制层
http://localhost:8080/mvc/user/t2?name=lcy&id=1&age=15
//提交是一个对象
@GetMapping("/t2")
public String test02(User user) {
//1.接收前端参数
System.out.println(user);
//3.跳转视图
return "hello";
}
public class ControllerTest01 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","hello world");
mv.setViewName("test");
return mv;
}
}
通过Model
@RequestMapping("/hello")
public String hello(Model model) {
//封装数据 向模式中添加msg与值,可以注解在JSP页面取出并渲染
model.addAttribute("msg","Hello,SpringMVCAnnotation");
return "hello"; //会被视图解析器处理
}
ModelMap
@GetMapping("/t3")
public String test3(@RequestParam("username") String name, ModelMap map) {
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
map.addAttribute("msg",name);
return "addPage";
}
对比
Model 只有几个方法,适合用于存储数据,简化了新手对Model对象的操作和理解
ModelMap 继承了LinkMap,除了实现自身的一些方法,有LinkeMap的方法和特性
ModelAndView 可以在存储数据的同时,可以设置返回的逻辑视图,进行控制展示层的跳转
<form action="${pageContext.request.contextPath}/e/t1" method="get">
<input type="text" name="username">
<input type="submit" value="提交">
</form>
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//转换成HttpServletRequest HttpServletResponse
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
<filter>
<filter-name>encodingfilter-name>
<filter-class>com.lcy.filter.EncodingFilterfilter-class>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/url-pattern>
filter-mapping>
<filter>
<filter-name>encodingfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
4.修改Tomcat配置文件:设置编码!
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URLEncoding="UTF-8"/>
一种轻量级的数据交换格式,提高网络传输效率,简洁和清晰的结构层次
前后端分离时代
后端部署后端,提供接口,数据
JSON
前端独立部署,负责渲染后端的数据
Title
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.10.2version>
dependency>
@RestController //整个类不会走视图解析器
public class UserController {
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
@RequestMapping("/j1") //返回一个对象
//@ResponseBody 就不会走视图解析器,会直接返回一个字符串
public String json1() throws JsonProcessingException {
//创建一个对象
User user = new User("陈平安",3,"男");
String stu = mapper.writeValueAsString(user);
return stu;
}
@RequestMapping("/j2") //返回集合
public String json2() throws JsonProcessingException {
ArrayList userList = new ArrayList<>();
User user1 = new User("陈平安1", 4, "男");
User user2 = new User("陈平安2", 4, "男");
User user3 = new User("陈平安3", 4, "男");
User user4 = new User("陈平安4", 4, "男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
String str = mapper.writeValueAsString(userList);
return str;
}
@RequestMapping("/j3") //返回时间对象
public String json3() throws JsonProcessingException {
//关闭时间戳的方式
// mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false);
Date date = new Date();
//自定义日期的格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//ObjectMapper,时间解析后的默认格式为:Timestamp时间戳
return mapper.writeValueAsString(sdf.format(date));
}
}
utils
public class JsonUtils {
public static String getJson(Object object,String dateFormat) {
ObjectMapper mapper = new ObjectMapper();
//关闭时间戳的方式
mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false);
//自定义日期的格式
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
public static String getJson(Object object){
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
}
控制层
@RestController //整个类不会走视图解析器
public class UserController {
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
@RequestMapping("/j1") //返回一个对象
//@ResponseBody 就不会走视图解析器,会直接返回一个字符串
public String json1() throws JsonProcessingException {
//创建一个对象
User user = new User("陈平安",3,"男");
return JsonUtils.getJson(user);
}
@RequestMapping("/j2") //返回集合
public String json2() throws JsonProcessingException {
ArrayList userList = new ArrayList<>();
User user1 = new User("陈平安1", 4, "男");
User user2 = new User("陈平安2", 4, "男");
User user3 = new User("陈平安3", 4, "男");
User user4 = new User("陈平安4", 4, "男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
return JsonUtils.getJson(userList);
}
@RequestMapping("/j3") //返回时间对象
public String json3() throws JsonProcessingException {
Date date = new Date();
return JsonUtils.getJson(date,"yyyy-MM-dd HH:mm:ss");
}
}
导入FastJson的jar包
com.alibaba
fastjson
1.2.68
转换JSON格式
@RequestMapping("/j4")
public String json4() throws JsonProcessingException {
ArrayList<User> userList = new ArrayList<>();
User user1 = new User("陈平安1", 4, "男");
User user2 = new User("陈平安2", 4, "男");
User user3 = new User("陈平安3", 4, "男");
User user4 = new User("陈平安4", 4, "男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
System.out.println("=============java对象转JSON字符串=======");
String str1 = JSON.toJSONString(userList);
System.out.println("JSON.toJSONString(List)=====>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)=====>"+str2);
System.out.println("=============JSON字符串转Java对象=======");
User user = JSON.parseObject(str2, User.class);
System.out.println("JSON.parseObject(str2, User.class)=====>"+user);
System.out.println("===========Java对象转JSON对象=========");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
System.out.println("=========JSON对象转Java对象==========");
User toJavaObject = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)====>"+toJavaObject);
return str1;
}
<mvc:annotation-driven>
<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>
异步的JavaScript和XMl
在无需重新加载整个网页的情况下,更新部门网页的技术
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
控制层
@RestController
public class AjaxController {
@RequestMapping("/t2")
public void test2(String name, HttpServletResponse resp) throws IOException {
System.out.println("接收了:"+name);
if ("lcy".equals(name)) {
resp.getWriter().print("true");
}else {
resp.getWriter().print("flase");
}
}
}
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
name
age
sex
<%-- 数据:后台--%>
控制器
@RequestMapping("/t3")
public List<User> test3() {
ArrayList<User> userList = new ArrayList<>();
//添加数据
userList.add(new User("java",1,"男"));
userList.add(new User("前端",1,"女"));
userList.add(new User("运维",1,"男"));
return userList;
}
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.0.js"></script>
<script>
function a1() {
$.ajax({
url:"${pageContext.request.contextPath}/t5",
data:{"username":$("#name").val()},
success:function (data) {
if (data.toString()=="ok"){
$("#userInfo").css("color","green").html(data);
}else {
$("#userInfo").css("color","red").html(data);
}
}
})
}
function a2() {
$.ajax({
url: "${pageContext.request.contextPath}/t5",
data: {"password":$("#pwd").val()},
success:function (data) {
if (data.toString()=="ok"){
$("#pwdInfo").css("color","green").html(data);
}else {
$("#pwdInfo").css("color","red").html(data);
}
}
})
}
</script>
</head>
<body>
<p>
用户名:<input type="text" id="name" onblur="a1()">
<span id="userInfo"></span>
</p>
<p>
密码:<input type="text" id="pwd" onblur="a2()">
<span id="pwdInfo"></span>
</p>
</body>
</html>
控制层
@RequestParam的require 默认是true
@RequestMapping("/t5")
public String a4(@RequestParam(required = false,value = "username") String name,@RequestParam(required = false,value = "password") String pwd) {
String msg = "";
if (name != null) {
if ("admin".equals(name)) {
System.out.println(name);
msg = "ok";
}else {
msg = "用户名有误";
}
}
if (pwd != null) {
if ("123".equals(pwd)) {
System.out.println(pwd);
msg = "ok";
}else {
msg = "密码错误";
}
}
return msg;
}
拦截器是AOP思想的具体应用
过滤器任何JavaWeb过程都可以使用
url-pattern中配置了/*之后,对所有要访问的资源进行拦截
拦截器是SpringMVC的工程才能使用
只会拦截访问的控制器方法,jsp/html/css…是不会拦截的
控制层
@Controller
@RequestMapping("/user")
public class LoginController {
@RequestMapping("/login") //登陆
public String login(HttpSession session, String username, String password) {
//把用户信息存在session中
session.setAttribute("userLoginInfo",username);
return "main";
}
@RequestMapping("/main")
public String main() {
return "main";
}
@RequestMapping("/goLogin")
public String login() {
return "login";
}
@RequestMapping("/goOut")
@ResponseBody
public String out(HttpSession session, HttpServletResponse response) throws IOException {
session.removeAttribute("userLoginInfo");
response.sendRedirect("/mvc_06/");
return "redirect:/user/index";
}
}
登陆页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登陆
登陆页面
初始页 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
登陆页面
首页
首页 main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
首页
首页
用户名:${userLoginInfo}
注销
spring-mvc.xml配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="com.lcy.config.LoginInterceptor"/>
mvc:interceptor>
mvc:interceptors>
拦截器配置
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//登陆页面也会放行
if (request.getRequestURI().contains("goLogin")) {
return true;
}
if (request.getRequestURI().contains("login")) {
return true;
}
//放行:判断什么情况下登陆
if (session.getAttribute("userLoginInfo") != null) {
return true;
}
//判断什么情况下是没有登陆的
request.getRequestDispatcher("/web/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
设置了enctype=“multipart/form-data”,浏览器会采用二进制流的方式来处理表单数据。
导入jar包、
commons-fileupload
commons-fileupload
1.4
javax.servlet
javax.servlet-api
4.0.1
provided
配置spring-mvc.xml id必须为multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
bean>
控制层(两种方法)
@RestController
public class FileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpload1(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException {
//获取文件名 file.getOriginalFilename()
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接返回首页
if ("".equals(uploadFileName)) {
return "redirect:/index.jsp";
}
System.out.println("上传文件名:"+uploadFileName);
//上传路径保存设置 UUID
String path = request.getServletContext().getRealPath("/upload");
//如果路径不在,创建一个
File realPath = new File(path);
if (!realPath.exists()) {
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream(); //文件输出流
FileOutputStream os = new FileOutputStream(new File(realPath, uploadFileName));//文件输出流
//读取写出
int len =0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件
file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));
return "redirect:/index.jsp";
}
}
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
@RequestMapping("/download")
public String downloads(HttpServletResponse response,HttpServletRequest request) throws Exception {
String name = request.getParameter("download");
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = name;
//1.设置响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
File file = new File(path, fileName);
//2.读取文件----输入流
FileInputStream input = new FileInputStream(file);
//3.写出文件-----输出流
ServletOutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index = 0;
//4.执行写出操作
while ((index = input.read(buff))!= -1){
out.write(buff,0,index);
out.flush();
}
out.close();
input.close();
return"ok";
}
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
下载
ing downloads(HttpServletResponse response,HttpServletRequest request) throws Exception {
String name = request.getParameter(“download”);
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = name;
//1.设置响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
File file = new File(path, fileName);
//2.读取文件----输入流
FileInputStream input = new FileInputStream(file);
//3.写出文件-----输出流
ServletOutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index = 0;
//4.执行写出操作
while ((index = input.read(buff))!= -1){
out.write(buff,0,index);
out.flush();
}
out.close();
input.close();
return"ok";
}
* jsp页面
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
下载