5. springboot-----项目实战-帐单管理系统(Thymeleaf)




1. 初始化项目

1. 创建并引入项目资源

在这里插入图片描述



2. Thymeleaf修改资源路径

使用 th:href 修改资源路径;好处是:会自动获取应用名

  1. 引用本地静态文件
    在这里插入图片描述

  2. 引用webjars文件(与上面的引用方式不同)
    在这里插入图片描述



3. Thymeleaf引入片段时传入参数

  1. 抽出重复部分的代码
    在这里插入图片描述

  1. 单独创建一个 .html , 给每段重复的代码取名字(这里是抽出来的重复代码)(使用的是Thymeleaf的语法格式)
    在这里插入图片描述

  1. 在页面引用抽出的重复代码 注意:这里main/public(完整路径: //classpath:/templates/public/list.html)前面不要加 / ,不然以jar包运行会运行不了
    在这里插入图片描述
    在这里插入图片描述

  2. 特殊部分:点击改变按钮显示的样式,这个部分需要传入一个值,在每次点击的时候判断传入的值
    这里三元运算符 --》 id=“avtive”,如果有这个属性,相应的< li>元素就会多一层css样式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述



4. 默认访问欢迎页(添加视图控制器)

  • 默认访问的欢迎页是 login.html,这里通过配置,我们可以直接访问 localhost:8080 直接访问到欢迎页,也可以通过 localhost:8080/index.html来访问

1.方法一: 通过实现一个匿名内部类实现(注意:这个类是专门用来写我们的配置类


@Configuration
public class MySpringMvcConfigurer {
	@Bean
	public WebMvcConfigurer webMvcConfigurer() {
		return new WebMvcConfigurer(){
			//添加视图控制(就是配置一个请求路径,然后会进入相应的页面)
            // (例:比如Controller层中有个login()方法的请求路径/login,它的返回值是"main/login",
            //       而我们想给login()再设置一个请求路径 / ,但是我们又不想运行login()方法,想直接返回"main/login",所以使用了如下配置)
			@Override
			public void addViewControllers(ViewControllerRegistry registry) {
				registry.addViewController("/").setViewName("main/login");
				registry.addViewController("/index.html").setViewName("main/login");
			}
		};
	}
}
  1. 方法二:下面的截图只是方法的演示,不是实现欢迎页的演示(注意:这个类也是专门用来写我们的配置类,但是我们现在使用的上面那种实现写入配置的方法
    在这里插入图片描述



5. 更改网页访问的图标

直接把图片放置到static静态目录中即可
在这里插入图片描述
在这里插入图片描述


6. SpringBoot国际化步骤

  1. 编写国际化配置文件,需要要显示的国际化内容写到配置中
    先修改 properties 文件的字符编码,不然出现乱码,进行如下设置:
    在这里插入图片描述

  2. 类路径下创建 i18n 目录存放配置文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


  1. Spring Boot 已经自动配置了管理国际化资源文件的组件 MessageSourceAutoConfiguration
    在这里插入图片描述

  1. 登录页面中通过 #{ } 获取国际化的值-------login.html 模板页面通过 #{} 属性获取国际化值
    在这里插入图片描述
    在这里插入图片描述

  2. 分析切换国际化原理
    原理 : LocaleResolver 获取区域信息对象, 来切换国际化信息 (区域信息就是像 zh_CN / en_US )
    通过上面分析, 是根据请求头带来的区域信息来选择对应的国际化信息, 即我们可以自定义区域信息解析

在这里插入图片描述



7. 点击链接切换国际化

  1. 请求参数中设置区域信息
<div style="margin-left: 100px;">
	<a th:href="@{/index.html(l='zh_CH')}" href="#">中文</a>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	<a th:href="@{/index.html(l='en_US')}" href="">English</a>
</div>

在这里插入图片描述


  1. 自定义区域信息解析器来进行设置区域信息
/**
* 自定义解析器来切换国际化信息,
* 需要再注入到容器器
* @Auther: www.mengxuegu.com
*/
public class MyLocaleResolver implements LocaleResolver {
	/**解析区域信息*/
	@Override
	public Locale resolveLocale(HttpServletRequest httpServletRequest) {
		System.out.println("区域信息。。。");
		//1. 获取请求头中的l参数值
		String l = httpServletRequest.getParameter("l");
		//2. 获取浏览器上的区域信息
		Locale locale = httpServletRequest.getLocale();
		//3. 获取当前操作系统 默认的区域信息
		// Locale locale = Locale.getDefault();
		//4. 参数有区域信息,则用参数里的区域信息
		if (!StringUtils.isEmpty(l)) {
			String[] split = l.split("_");
			//参数:语言代码,国家代码
			locale = new Locale(split[0], split[1]);
		}
		return locale;
	}
	@Override
	public void setLocale(HttpServletRequest httpServletRequest,
		HttpServletResponse httpServletResponse, Locale locale) {
	}
}

  1. 需要替换mvc自动配置类中区域信息解析器,(返回值与方法名要和下面保持必须一致)(上面设置的访问欢迎页的配置也是写在这个类当中
    在这里插入图片描述



2.登录模块开发

1. 登录控制层

在这里插入图片描述在这里插入图片描述


2. 自定义拦截器-登录校验

  1. 成功登陆之后,把用户名信息存入到session中去
    在这里插入图片描述

  1. 书写拦截器类

/**
 * 定义登录拦截器
 * @Auther: 梦学谷
 */
public class LoginHandlerInterceptor implements HandlerInterceptor {

    //调用目标方法之前被拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	//1. 获取session中loginUser是否有值
        Object loginUser = request.getSession().getAttribute("loginUser");
        if( loginUser != null) {
            //已经登录过,放行
            return true;
        }
        //2. 没有登录过,直接转发到首页(重定向不能携带值所以使用转发)
        request.setAttribute("msg", "没有权限,请先登录!");
        request.getRequestDispatcher("/index.html").forward(request, response);
        return false;
    }
}


  1. 把拦截器添加到配置类中(就是上面标红的那个配置类
        //添加过滤器
         @Override
         public void addInterceptors(InterceptorRegistry registry) {
             registry.addInterceptor(new LoginHandlerInterceptor())
                     //指定要拦截的请求 /** 表示拦截所有请求
                     .addPathPatterns("/**")
                     //排除不需要拦截的请求路径
                     .excludePathPatterns("/", "/index.html", "/login")
                     //springboot2+之后需要将静态资源文件的访问路径 也排除
                     .excludePathPatterns("/css/*", "/img/*","/js/*");
         }

在这里插入图片描述




3.主页模块开发

1.退出系统



2. 供应商列表查询(顺带查询功能)

  1. 更改模板里面点击供应商的链接(public.html)
    在这里插入图片描述

  1. 书写后端代码(controller层 --> ProviderController.java)这个实例暂时没有用到数据库,没有service层,dao层都是自己写的查询本地数据的代码
@Controller
public class ProviderController {
    //获取日志类
    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    ProviderDao providerDao;

	/*
	注解@RequestParam(value="providerName", required = false)  String providerName
			value="providerName"表示前端传入的值的名字
			 required = false表示这个值可以为空
	
	*/
	
    //@RequestMapping( value="/providers", method = RequestMethod.GET)
    @GetMapping("/providers")
    public String list(Map<String, Object> map,@RequestParam(value="providerName", required = false) String providerName) {
        //1. 打印日志
        logger.info("供应商列表查询。。。" + providerName);
        
        //2. 通过传入的 providerName 查询所有的供应商(Collection是set list 的顶层接口)(这里传入值就可以通过这个值查询数据)
        Collection<Provider> providers = providerDao.getAll(providerName);
        
        //3. 把查询到的供应商放到map中,把前端传入的值 providerName 也放入map中
        map.put("providers", providers);
        map.put("providerName", providerName);
        //classpath:/templates/
        //classpath:/templates/provider/list.html
        
        //4. 转发到list.html页面
        return "provider/list";
    }
 }

3.前端获取map对象 在这里插入图片描述
在这里插入图片描述



3. 供应商详情查询

在这里插入图片描述

  1. 书写这个详细按钮的前端代码(list.html)
<td>
	<a th:href="@{/provider/} + ${p.pid}" href="view.html">
		<img th:src="@{/img/read.png}" src="../img/read.png" alt="查看" title="查看"/>
	</a>
	<a th:href="@{/provider/} + ${p.pid} +'?type=update'" href="update.html">
		<img th:src="@{/img/xiugai.png}"  src="../img/xiugai.png" alt="修改" title="修改"/>
	</a>
	<a th:attr="del_uri=@{/provider/}+${p.pid}"  href="#" class="delete" >
		<img th:src="@{/img/schu.png}"  src="../img/schu.png" alt="删除" title="删除"/>
	</a>
</td>

2.


  1. 书写后端代码,用于查询它的详细信息,并返回跳转到详情页(ProviderController.java)
    /**
     * type = null 进入查看详情页面view.html,
     * type=update 则是进入update.html
     * @param pid 供应商id
     * @param type
     * @param map
     * @return
     */
    @GetMapping("/provider/{pid}")
    public String view(@PathVariable("pid") Integer pid,
                       @RequestParam(value="type", defaultValue = "view") String type,
                       Map<String, Object> map) {
        logger.info("查询" + pid + "的供应商详细信息");

        Provider provider = providerDao.getProvider(pid);

        map.put("provider", provider);

//        return "provider/view";
        // type = null 则进入view.html, type=update 则是进入update.html
        return "provider/" + type;
    }

  1. 详情页的一些代码(view.html)

在这里插入图片描述



4. 供应商修改

  1. 修改修改按钮的提交链接
    在这里插入图片描述
  2. 修改上面使用过的后端方法,进入修改页面(ProviderController.java);与上面查询使用的是同一个方法
    /**
     * type = null 进入查看详情页面view.html,
     * type=update 则是进入update.html
     * @param pid 供应商id
     * @param type
     * @param map
     * @return
     */
    @GetMapping("/provider/{pid}")
    public String view(@PathVariable("pid") Integer pid,
                       @RequestParam(value="type", defaultValue = "view") String type,
                       Map<String, Object> map) {
        logger.info("查询" + pid + "的供应商详细信息");

        Provider provider = providerDao.getProvider(pid);

        map.put("provider", provider);

//        return "provider/view";
        // type = null 则进入view.html, type=update 则是进入update.html
        return "provider/" + type;
    }

在这里插入图片描述

  1. 进入修改页面,并回显相应的信息(update.html)
<form id="updateForm" action="#" th:action="@{/provider}" th:method="post">
                <!--发送put请求修改供应商信息-->

                <!--1. 在SpringMVC中配置HiddenHttpMethodFilter(SpringBoot自动配置好了)-->
                <!--2. 页面创建一个method="post"表单-->
                <!--3. 创建一个input标签 name="_method",value="指定请求方式"-->
                <input th:type="hidden" name="_method" value="put">
                <input th:type="hidden" name="pid" th:value="${provider.pid}">
                <div class="">
                    <label for="providerName">供应商名称:</label>
                    <input type="text" th:value="${provider.providerName}" name="providerName" id="providerName" placeholder="测试供应商001"/>
                    <span >*</span>
                </div>
                <div>
                    <label for="people">联系人:</label>
                    <input type="text" th:value="${provider.people}" name="people" id="people" placeholder="韩露"/>
                    <span>*</span>

                </div>
                <div>
                    <label for="phone">联系电话:</label>
                    <input type="text" th:value="${provider.phone}" name="phone" id="phone" placeholder="15918230478"/>
                    <span></span>
                </div>
                <div>
                    <label for="address">联系地址:</label>
                    <input type="text" th:value="${provider.address}" name="address" id="address" placeholder="北京"/>
                    <span></span>

                </div>
                <div>
                    <label for="fax">传真:</label>
                    <input type="text" th:value="${provider.fax}" name="fax" id="fax" placeholder="15918230478"/>
                    <span></span>

                </div>
                <div>
                    <label for="describe">描述:</label>
                    <input type="text" th:value="${provider.describe}" name="describe" id="describe" placeholder="描述"/>
                    <span></span>

                </div>
                <div class="providerAddBtn">
                    <!--<a href="#">保存</a>-->
                    <!--<a href="providerList.html">返回</a>-->
                    <input type="button" value="保存" onclick="$('#updateForm').submit()"/>
                    <input type="button" value="返回" onclick="history.back(-1)"/>
                </div>
            </form>

在这里插入图片描述

  1. 后端接收修改之后的信息(ProviderController.java)

    //修改供应商信息
    @PutMapping("/provider")
    public String update(Provider provider) {//这个方法里面的形参就是前端修改的参数
        logger.info("更改供应商信息。。。");
        //更新操作
        providerDao.save(provider);

        return "redirect:providers";
    }

          SpringMVC会自动将请求参数与形参对象的属性一一绑定
          要求:请求参数名要与形参对象的属性名相同

在这里插入图片描述



5. 供应商添加

  1. 修改添加按钮的链接,并在后端写好跳转到增加页面的方法
    列表页面(list.html)
    //前往添加 页面
    @GetMapping("/provider")
    public String toAddPage() {
        return "provider/add";
    }

在这里插入图片描述


  1. 增加方法页面点击按钮保存方法,并跳转到供应商列表
    在这里插入图片描述
    在这里插入图片描述
    //添加数据
    //SpringMVC会自动将请求参数与形参对象的属性一一绑定
	//要求:请求参数名要与形参对象的属性名相同
    @PostMapping("/provider")
    public String add(Provider provider) {
        logger.info("添加供应商数据" + provider);
        //保存数据操作
        providerDao.save(provider);
		//添加完成,回到供应商列表页面
		//通过redirect重定向 或forward转发到一个请求地址, / 代表当前项目路径
        return "redirect:/providers";
    }



6. 供应商删除

  1. 点击删除按钮,会把相应的列表项的主键提取出来,
    在这里插入图片描述

  1. 并弹出是否删除的弹窗(js.js)
//列表页面上点击删除按钮弹出删除框
$(function () {
    $('.delete').click(function () {
        //灰背景遮挡效果
        $('.zhezhao').css('display', 'block');
        $('#removeProv').fadeIn();
        //获取点击删除的那个按键的del_uri,然后赋值给提交删除表单的那个action
        $("#deleteForm").attr("action", $(this).attr("del_uri"));
    });
    //点击 确定
    $('#yes').click(function () {
        $("#deleteForm").submit();
        $('.zhezhao').css('display', 'none');
        $('#removeProv').fadeOut();
    });
    //点击 取消
    $('#no').click(function () {
        $('.zhezhao').css('display', 'none');
        $('#removeProv').fadeOut();
    });
});

在这里插入图片描述

<!--点击删除按钮后弹出的页面-->
<div class="zhezhao"></div>
<form method="post" id="deleteForm">
    <input type="hidden" name="_method" value="delete">
    <div class="remove" id="removeProv">
        <div class="removerChid">
            <h2>提示</h2>
            <div class="removeMain" >
                <p>你确定要删除吗?</p>
                <a href="#" id="yes">确定</a>
                <a href="#" id="no">取消</a>
            </div>
        </div>
    </div>
</form>

在这里插入图片描述


  1. 点击删除按钮删除相应列表项(ProviderController.java)
    //删除供应商
    @DeleteMapping("/provider/{pid}")
    public String delete(@PathVariable("pid") Integer pid) {
        logger.info("删除操作, pid=" + pid);
        providerDao.delete(pid);
        return "redirect:/providers";
    }

在这里插入图片描述




3. 总结:分析 Restful 架构

1. Restful 架构: 通过HTTP请求方式来区分对资源CRUD操作, 请求 URI 是 /资源名称/资源标识

对比下 :注意我们上面写的增删改查,使用的都是同一个提交地址,但是我们使用的是不同的注解
在这里插入图片描述



2. 项目使用Rest处理架构

在这里插入图片描述



3. 总结项目中的增删改查方法的提交地址

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36354011/article/details/86746251
今日推荐