龙空技术网

第八章:SpringMVC自动配置

源码解析 141

前言:

今天兄弟们对“格式化转换器”都比较关怀,同学们都需要剖析一些“格式化转换器”的相关知识。那么小编也在网上收集了一些有关“格式化转换器””的相关知识,希望朋友们能喜欢,我们快快来学习一下吧!

1、SpringMVC的自动导入

Spring框架

自动配置好了mvc:

以下是SpringBoot对SpringMVC的默认

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.

The auto-configuration adds the following features on top of Spring’s defaults:

Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))ContentNegotiatingViewResolver组合所有视图解析器如何定制:我们可以自己给容器中添加一个视图解析器;自动将其整合进来Support for serving static resources, including support for WebJars (see below).静态资源Static index.html support.Custom Favicon support (see below).自动注册 了Converter, GenericConverter, Formatter beans.Converter:类型转换 文本转为字面量Formatter :格式化器 转换后格式转换@Bean @ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")//在文件配置入职格式化的规则 public Formatter<Date> dateFormatter() { return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件 }自己添加的格式化转换器,只需要放在容器中即可Support for HttpMessageConverters (see below).HttpMessageConverters :转换HTTP转换和响应:User - jsonHttpMessageConverters :是从容器中确定;获取所有的HttpMessageConverters ,将自己的组件注册在容器中@BeanIf you need to add or customize converters you can use Spring Boot’s HttpMessageConverters class:import org.springframework.boot.autoconfigure.web.HttpMessageConverters; import org.springframework.context.annotation.*; import org.springframework.http.converter.*; @Configuration public class MyConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter<?> additional = ... HttpMessageConverter<?> another = ... return new HttpMessageConverters(additional, another); } }Automatic registration of MessageCodesResolver (see below).定义错误代码生成规则Automatic use of a ConfigurableWebBindingInitializer bean (see below).@Override protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() { try { return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class); } catch (NoSuchBeanDefinitionException ex) { return super.getConfigurableWebBindingInitializer(); } }在beanFactory:中可以自己创建一个,初始化webDataBinder请求数据 ==》javaBean

If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.) you can add your own @Configuration class of type WebMvcConfigurerAdapter, but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter or ExceptionHandlerExceptionResolver you can declare a WebMvcRegistrationsAdapter instance providing such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

思想:修改默认配置

2、扩展SpringMVC

编写一个配置类,类型是WebMvcConfigurerAdapter(继承),使用WebMvcConfigurerAdapter可以扩展,不能标注@EnableWebMvc;既保留了配置,也能拓展我们自己的应用

@Configurationpublic class MyMvcConfig extends WebMvcConfigurerAdapter {    @Override    public void addViewControllers(ViewControllerRegistry registry) {//        super.addViewControllers(registry);        //浏览器发送wdjr请求,也来到success页面        registry.addViewController("/wdjr").setViewName("success");    }}

原理:

1)、WebMvcAutoConfiguration是SpringMVC的自动配置

2)、在做其他自动配置时会导入;@Import(EnableWebMvcConfiguration.class)

@Configurationpublic static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();	//从容器中获取所有webMVCconfigurer	@Autowired(required = false)	public void setConfigurers(List<WebMvcConfigurer> configurers) {		if (!CollectionUtils.isEmpty(configurers)) {			this.configurers.addWebMvcConfigurers(configurers);                        	@Override                protected void addViewControllers(ViewControllerRegistry registry) {                    this.configurers.addViewControllers(registry);                }            //一个参考实现,将所有的webMVCconfigurer相关配置一起调用(包括自己的配置类)            	@Override               // public void addViewControllers(ViewControllerRegistry registry) {                   // for (WebMvcConfigurer delegate : this.delegates) {				 //delegate.addViewControllers(registry);                    //}                }		}	}    

3)、自己的配置被调用

效果:SpringMVC的自动配置和我们的扩展配置都会起作用

3、全面接管mvc

不需要SpringBoot对SpringMVC的自动配置。

@EnableWebMvc@Configurationpublic class MyMvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {//        super.addViewControllers(registry);        //浏览器发送wdjr请求,也来到success页面        registry.addViewController("/wdjr").setViewName("success");    }}

例如静态资源访问,不推荐全面接管

原理:

为什么@EnableWebMvc注解,SpringBoot对SpringMVC的控制就失效了

1)、核心配置

@Import(DelegatingWebMvcConfiguration.class)public @interface EnableWebMvc {}

2)、DelegatingWebMvcConfiguration

@Configurationpublic class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

3)、WebMvcAutoConfiguration

@Configuration@ConditionalOnWebApplication@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,      WebMvcConfigurerAdapter.class })//容器没有这个组件的时候,这个自动配置类才生效@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,      ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration {

4)、@EnableWebMvc将WebMvcConfigurationSupport导入进来了;

5)、导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能

5、修改SpringMVC默认配置

模式:

1)、SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;

​ 2)、在SpringBoot中会有 xxxConfigurer帮助我们扩展配置。

6、RestfulCRUD1、默认访问首页

在config/MyConfig.java中编写配置类

//所有的webMvcConfigurerAdapter组件会一起起作用@Bean //註冊到容器去public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){    WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {        @Override        public void addViewControllers(ViewControllerRegistry registry) {            registry.addViewController("/").setViewName("login");            registry.addViewController("/login.html").setViewName("login");        }    };    return adapter;}

静态资源引用

<link href="#" th:href="@{/css/signin.css}" rel="stylesheet" />
2、国际化

1、编写国际化配置文件

2、使用ResourceBundleMessageSource管理国际化资源文件

3、在页面中使用fmt:message,取出国际化内容

1、浏览器切换国际化

步骤

1、编写国际化配置文件,抽取页面需要的显示的国际化消息

2、SpringBoot自动配置好了国际化配置的资源文件

@ConfigurationProperties(prefix = "spring.messages")public class MessageSourceAutoConfiguration {    //我们的配置文件可以直接放在类路径下叫messages.properties    private String basename = "messages";    @Bean	public MessageSource messageSource() {		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();		if (StringUtils.hasText(this.basename)) {            //设置国际化文件的基础名,去掉语言国家代码			messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(					StringUtils.trimAllWhitespace(this.basename)));		}		if (this.encoding != null) {			messageSource.setDefaultEncoding(this.encoding.name());		}		messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);		messageSource.setCacheSeconds(this.cacheSeconds);		messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat);		return messageSource;	}

3、对IDEA的编码进行设置

4、login进行标签插入

<!DOCTYPE html><!-- saved from url=(0051) --><html lang="en" xmlns:th=";><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />    <meta name="description" content="" />    <meta name="author" content="" />    <link rel="icon" href="; />    <title>登录页面</title>    <!-- Bootstrap core CSS -->    <link href="#" th:href="@{/css/bootstrap.min.css}" rel="stylesheet" />    <!-- Custom styles for this template -->    <link href="./login_files/signin.css" th:href="@{/css/signin.css}" rel="stylesheet" />  </head>  <body class="text-center">    <form class="form-signin">      <img class="mb-4" src="./login_files/bootstrap-solid.svg" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72" />      <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>      <label  class="sr-only" th:text="#{login.username}">Username</label>      <input type="text"  name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus=""/>      <label for="inputPassword" class="sr-only" th:text="#{login.password}">Password</label>      <input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="" />      <div class="checkbox mb-3">        <label>          <input type="checkbox" value="remember-me" /> [[#{login.remember}]]        </label>      </div>      <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>      <p class="mt-5 mb-3 text-muted">© 2017-2018</p>    </form>  </body></html>

效果根据浏览器语言的信息切换国际化

原理:

国际化locale(区域信息对象);LocaleResolver(获取区域对象);

@Bean@ConditionalOnMissingBean@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")public LocaleResolver localeResolver() {    if (this.mvcProperties        .getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {        return new FixedLocaleResolver(this.mvcProperties.getLocale());    }    AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();    localeResolver.setDefaultLocale(this.mvcProperties.getLocale());    return localeResolver;}            

默认的就是根据请求头带来的区域信息获取local国际化信息(截图就是这么犀利)

2、点击链接切换国际化

自己编写localResolver,加到容器中

1、更改HTML代码

<p class="mt-5 mb-3 text-muted">© 2017-2018</p>  <a href="#" class="btn btn-sm" th:href="@{/index.html?lg=zh_CN}">中文</a>  <a href="#" class="btn btn-sm" th:href="@{/index.html?lg=en_US}">English</a>

2、新建一个MyLocaleResolver.class

public class MyLocaleResolver implements LocaleResolver {    //解析区域信息    @Override    public Locale resolveLocale(HttpServletRequest request) {        String l = request.getParameter("lg");        Locale locale = Locale.getDefault();        if(!StringUtils.isEmpty(l)){            String[] split = l.split("_");            locale = new Locale(split[0], split[1]);        }        return locale;    }    @Override    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {    }}

3、将MyLocaleResolver加入到容器中

@Beanpublic LocaleResolver localeResolver(){    return new MyLocalResolver();}

4、启动演示

3、登录拦截器1、登录

开发技巧

​ 1、清除模板缓存

​ 2、Ctrl+F9刷新

1、新建一个LoginController

@Controllerpublic class LoginController {    @PostMapping(value ="/user/login")    public String login(@RequestParam("username")String username,                        @RequestParam("password")String password,                        Map<String,Object> map){        if(!StringUtils.isEmpty(username) && "123456".equals(password)){            //登录成功            return "list";        }else{            map.put("msg", "用户名密码错误");            return "login";        }    }}

2、登录错误消息显示

<!--判断--><p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

3、表单重复提交

表单重复提交事件 --》重定向来到成功页面--》模板引擎解析

if(!StringUtils.isEmpty(username) && "123456".equals(password)){    //登录成功,防止重复提交    return "redirect:/main.html";}else{    map.put("msg", "用户名密码错误");    return "login";}

模板引擎解析

@Overridepublic void addViewControllers(ViewControllerRegistry registry) {    registry.addViewController("/").setViewName("login");    registry.addViewController("/index.html").setViewName("login");    registry.addViewController("/main.html").setViewName("Dashboard");}
4、拦截器

作用:实现权限控制,每个页面请求前中后,都会进入到拦截器进行处理(登录权限)

1、在component下新建一个LoginHandlerInterceptor拦截器

public class LoginHandlerInterceptor implements HandlerInterceptor {    //目标方法执行之前    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        Object user = request.getSession().getAttribute("loginUser");        if(user!=null){            //已经登录            return true;        }        //未经过验证        request.setAttribute("msg", "没权限请先登录");        request.getRequestDispatcher("/index.html").forward(request, response);        return false;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {    }}

2、在MyMvcConfig配置中重写拦截器方法,加入到容器中

//所有的webMvcConfigurerAdapter组件会一起起作用@Bean //註冊到容器去public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){    WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {        @Override        public void addViewControllers(ViewControllerRegistry registry) {            registry.addViewController("/").setViewName("login");            registry.addViewController("/index.html").setViewName("login");            registry.addViewController("/main.html").setViewName("Dashboard");        }        //注册拦截器        @Override        public void addInterceptors(InterceptorRegistry registry) {            //静态资源 css js img 已经做好了静态资源映射            registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").                    excludePathPatterns("/index.html","/","/user/login");        }    };    return adapter;}

3、在LoginHandler中添加登录成功写入session

@Controllerpublic class LoginController {    @PostMapping(value ="/user/login")    public String login(@RequestParam("username")String username,                        @RequestParam("password")String password,                        Map<String,Object> map,                        HttpSession session){        if(!StringUtils.isEmpty(username) && "123456".equals(password)){            //登录成功,防止重复提交            session.setAttribute("loginUser", username);            return "redirect:/main.html";        }else{            map.put("msg", "用户名密码错误");            return "login";        }    }}
5、CRUD-员工列表

实验要求:

1)、RestfulCRUD:CRUD满足Rest风格

URI:/资源名称/资源标识+HTTP操作

普通CRUD

RestfulCRUD

查询

getEmp

emp -- GET

添加

addEmp?xxx

emp --POST

修改

updateEmp?id=xxx&xxx=xx

emp/{id} -- PUT

删除

deleteEmp?id=1

emp/{id} --DELETE

2、实验的请求架构

请求URI

请求方式

查询所有员工

emps

GET

查询某个员工

emp/{id}

GET

添加页面

emp

GET

添加员工

emp

POST

修改页面(回显)

emp/{id}

GET

修改员工

emp/{id}

PUT

删除员工

emp/{id}

DELETE

3、员工列表

1、公共页面抽取

使用方法

1、抽取公共片段<!--footer.html--><div id="footid" th:fragment="copy">xxx</div>2、引入公共片段<!--test.html--><div th:insert=~{footer::copy}></div>~{templatename::selector} 模板名::选择器  footer::#footid~{templatename::fragmentname} 模板名::片段名称 footer::copy行内写法可以加~{xx::xx} 标签体可以 xx::xx

三种引用方式

th:insert :加个外层标签 +1

th:replace :完全替换 1

th:include:就替换里面的内容 -1

公共页面

<body>	...    <div th:insert="footer :: copy"></div>    <div th:replace="footer :: copy"></div>    <div th:include="footer :: copy"></div></body>

结果

<body>...    <!-- th:insert -->    <div>        <footer>            © 2011 The Good Thymes Virtual Grocery        </footer>    </div>    <!--th:replace-->    <footer>   		© 2011 The Good Thymes Virtual Grocery    </footer>    <!--th:include-->    <div>        © 2011 The Good Thymes Virtual Grocery    </div></body>

用此种方法将公共页面引入

2、列表高亮

引入片段的时候传入参数,新建一个commons文件夹存储公共页面bar.html

模板引入变量名

dashboard

<a class="nav-link active"   th:class="${activeUri}=='main.html'?'nav-link active':'nav-link'"   href="; th:href="@{/main.html}">    <svg xmlns="; width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>    Dashboard <span class="sr-only">(current)</span></a>

员工管理

<li class="nav-item">    <a class="nav-link"       th:class="${activeUri}=='emps'?'nav-link active':'nav-link'"       href="; th:href="@{/emps}">        <svg xmlns="; width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>        员工管理    </a>

引入模板的时候传入参数

dashboard.html引入

<!--引入侧边栏-->   <div th:replace="commons/bar :: sidebar(activeUri='main.html')"></div>

list.html引入

<!--引入侧边栏--><div th:replace="commons/bar::sidebar(activeUri='emps')"></div>
6、列表数据显示(查)1、传入员工对象

EmployeeController类,传入员工对象

@Controllerpublic class EmployeeController {    @Autowired    EmployeeDao employeeDao;    /**     * 查询所有员工返回列表页面     */    @GetMapping(value = "/emps")    public String list(Model model){        Collection<Employee> employees = employeeDao.getAll();        model.addAttribute("emps",employees);        return "emp/list";    }}
2、 遍历对象

list.html中 使用模板的 th:each方法

table class="table table-striped table-sm">    <thead>    <tr>        <th>#</th>        <th>lastName</th>        <th>email</th>        <th>gender</th>        <th>department</th>        <th>birth</th>        <th>操作</th>    </tr>    </thead>    <tbody>        <tr th:each="emp:${emps}">            <td th:text="${emp.id}">1</td>            <td th:text="${emp.lastName}">1</td>            <td th:text="${emp.email}">1</td>            <td th:text="${emp.gender}">1</td>            <td th:text="${emp.department.departmentName}">1</td>            <td th:text="${#dates.format(emp.birth,'yyyy-MM-dd HH:mm:ss')}">1</td>            <td>                <button class="btn btn-sm btn-primary">编辑</button>                <button class="btn btn-sm btn-danger">删除</button>            </td>        </tr>    </tbody></table>
3、效果显示7、员工添加(增)

功能:点击添加按钮,出现新增页面

1、新增页面

<form>    <!-- LastName -->    <div class="form-group">        <label for="LastName">LastName</label>        <input type="text" class="form-control" id="LastName"  placeholder="LastName">    </div>    <!-- Email -->    <div class="form-group">        <label for="Email">Email</label>        <input type="email" class="form-control" id="Email"  placeholder="zhangsan@163.com">    </div>    <!--gender-->    <div class="form-group">        <label >Gender</label><br/>        <div class="form-check form-check-inline">            <input class="form-check-input" type="radio" name="gender" value="1">            <label class="form-check-label" >男</label>        </div>        <div class="form-check form-check-inline">            <input class="form-check-input" type="radio" name="gender" value="0">            <label class="form-check-label" >女</label>        </div>    </div>    <!-- department -->    <div class="form-group">        <label for="exampleFormControlSelect1">department</label>        <select class="form-control" id="exampleFormControlSelect1">            <option th:each="dept:${depts}" th:value="${dept.id}" th:text="${dept.departmentName}"></option>        </select>    </div>    <!--Birth-->    <div class="form-group">        <label for="birthDate">Birth</label>        <input type="text" class="form-control" id="birthDate" placeholder="2012-12-12">    </div>    <button type="submit" class="btn btn-primary">添 加</button></form>
2、页面跳转

在EmployeeController中添加addEmpPage方法

/** * 添加员工 */@GetMapping(value = "/emp")public String toAddPage(Model model){    //来到添加页面,查出所有部门显示    Collection<Department> depts = departmentDao.getDepartments();    model.addAttribute("depts",depts);    return "emp/add";}

关键点:在添加部门页面要遍历部门信息,所以在方法中出入部门信息

3、添加功能完成

新建一个PostMapping

ThymeleafViewResolver 查看redirect和forward,原生的sendredirect方法;

1、新建一个postMapping的方法用来接受页面的添加POST请求

/** * 员工添加 */@PostMapping(value = "/emp")public String addEmp(Employee employee){    employeeDao.save(employee);    //来到员工列表页面、redirect:重定向到一个地址,forward转发到一个地址    return "redirect:/emps";}

2、修改添加页面,添加name属性

<form th:action="@{/emp}" method="post">    <!-- LastName -->    <div class="form-group">        <label for="LastName">LastName</label>        <input type="text" class="form-control" id="LastName" name="lastName" placeholder="LastName">    </div>    <!-- Email -->    <div class="form-group">        <label for="Email">Email</label>        <input type="email" class="form-control" id="Email"  name="email" placeholder="zhangsan@163.com">    </div>    <!--gender-->    <div class="form-group">        <label >Gender</label><br/>        <div class="form-check form-check-inline">            <input class="form-check-input" type="radio" name="gender" value="1">            <label class="form-check-label" >男</label>        </div>        <div class="form-check form-check-inline">            <input class="form-check-input" type="radio" name="gender" value="0">            <label class="form-check-label" >女</label>        </div>    </div>    <!-- department -->    <div class="form-group">        <label >department</label>        <select class="form-control"  name="department.id">            <option th:each="dept:${depts}" th:value="${dept.id}" th:text="${dept.departmentName}"></option>        </select>    </div>    <div class="form-group">        <label for="birthDate">Birth</label>        <input type="text" class="form-control" id="birthDate" placeholder="2012-12-12" name="birth">    </div>    <button type="submit" class="btn btn-primary">添 加</button></form>

1、部门对象问题?

<select class="form-control"  name="department.id">

2、日期格式化?

属性中添加 date-formate 默认是 /

@Bean@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")public Formatter<Date> dateFormatter() {   return new DateFormatter(this.mvcProperties.getDateFormat());}@Overridepublic MessageCodesResolver getMessageCodesResolver() {   if (this.mvcProperties.getMessageCodesResolverFormat() != null) {      DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();      resolver.setMessageCodeFormatter(            this.mvcProperties.getMessageCodesResolverFormat());      return resolver;   }   return null;}
spring.mvc.date-format=yyyy-MM-dd
8、员工编辑(改)

思路使用add页面,并且数据回显,然后区分添加,PUT请求

1、修改按钮

在list.html的编辑按钮加上链接

<td>    <a  href="#" th:href="@{/emp/}+${emp.id}" class="btn btn-sm btn-primary">编辑</a>    <button class="btn btn-sm btn-danger">删除</button></td>
2、编写跳转页面

跳转到员工编辑页面的Controller

/** * 员工编辑页面 */@GetMapping(value = "/emp/{id}")public String toEditPage(@PathVariable("id") Integer id ,Model model){    Employee emp = employeeDao.getEmpById(id);    Collection<Department> departments = departmentDao.getDepartments();    model.addAttribute("emp",emp);    model.addAttribute("depts",departments);    return "emp/add";}   
3、对页面修改

对add页面进行修改

1)、添加回显

2)、添加判断是否emp!=null(区分add or edit)

3)、添加put请求 --两个input的hidden标签

 <form th:action="@{/emp}" method="post">        <!--发送put请求-->        <!--1.SpringMVC配置HiddenHttpMethodFilter            2.页面创建一个post表单            3.创建一个 input name_method 值就是我们请求的方式-->        <input type="hidden" name="_method" value="put" th:if="${emp!=null}">        <input type="hidden" name="id" th:value="${emp.id}" th:if="${emp!=null}">        <!-- LastName -->        <div class="form-group">            <label for="LastName">LastName</label>            <input type="text" class="form-control" id="LastName" name="lastName" placeholder="LastName" th:value="${emp!=null}?${emp.lastName}">        </div>        <!-- Email -->        <div class="form-group">            <label for="Email">Email</label>            <input type="email" class="form-control" id="Email"  name="email" placeholder="zhangsan@163.com" th:value="${emp!=null}?${emp.email}">        </div>        <!--gender-->        <div class="form-group">            <label >Gender</label><br/>            <div class="form-check form-check-inline">                <input class="form-check-input" type="radio" name="gender" value="1" th:checked="${emp!=null}?${emp.gender}==1">                <label class="form-check-label" >男</label>            </div>            <div class="form-check form-check-inline">                <input class="form-check-input" type="radio" name="gender" value="0" th:checked="${emp!=null}?${emp.gender}==0">                <label class="form-check-label" >女</label>            </div>        </div>        <!-- department -->        <div class="form-group">            <label >department</label>            <select class="form-control"  name="department.id" >                <option th:selected="${emp!=null}?${dept.id == emp.department.id}" th:each="dept:${depts}" th:value="${dept.id}" th:text="${dept.departmentName}"></option>            </select>        </div>        <div class="form-group">            <label for="birthDate">Birth</label>            <input type="text" class="form-control" id="birthDate" placeholder="2012-12-12" name="birth" th:value="${emp!=null}?${#dates.format(emp.birth,'yyyy-MM-dd HH:mm:ss')}">        </div>        <button type="submit" class="btn btn-primary" th:text="${emp!=null}?'修改':'添加'">添 加</button>    </form></main>
9、员工删除(删)1、新建Contoller
/** * 员工删除 */@DeleteMapping(value = "/emp/{id}")public String deleteEmp(@PathVariable("id") Integer id){    employeeDao.deleteEmpById(id);    return "redirect:/emps";}
2、修改删除标签
<button th:attr="del_uri=@{/emp/}+${emp.id}"  class="btn btn-sm btn-danger deleteBtn">    删除</button>
3、写Form表单

form表单卸载外面,input 中 name="_method" value="delete" 模拟delete请求

                </tbody>            </table>        </div>    </main>    <form id="deleteEmpForm" method="post">        <input type="hidden" name="_method" value="delete">    </form></div>
4、写JS提交
<script>    $(".deleteBtn").click(function () {        $("#deleteEmpForm").attr("action",$(this).attr("del_uri")).submit();        return false;    })</script>

return false;禁用btn提交效果

标签: #格式化转换器