关于SpringMVC的一点学习笔记

1、 maven依赖/目录结构

  1. pom文件
    大型工程可转列一个公共common模块,用于提供公共的方法类,如日期格式处理、SMS短信等;
    设置一个interface接口模块,用于Controller与Service分离的情况(如dubbo等),但对于小工程这种分离会降低调试效率,因为Controller与Service是分离的,通过接口的maven install来更新,比较慢。可先开发,后分离。
    参考一个较为齐全的pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>health_parent</artifactId>
        <groupId>cn.cathayinfo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>health_common</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
        </dependency>
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.miemiedev</groupId>
            <artifactId>mybatis-paginator</artifactId>
        </dependency>

        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>
        <!-- dubbo相关 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
        </dependency>


        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
            <version>1.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>


    </dependencies>
</project>
  1. 父子工程:parent
    parent组织全部工程,并统一依赖版本
  2. build:Tomcat轻量级Tomcat,可不依赖于本机的Tomcat,使得开发和上线运行容器环境一致
 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>80</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
  1. 目录结构:src->main->java/resource/webapp
    maven的骨架结构,可自建和使用骨架。

2、配置文件

  1. web.xml
    要点:
    (1)将springmvc作为默认处理请求的DispatcherServlet
<servlet>
  <servlet-name>springmvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value> <!-- 通过这里将web.xml与springmvc.xml发生关联 -->
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>

(2)处理编码问题

<filter>
  <filter-name>CharacterEncodingFilter</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>
  <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

(3)采用系统登录的话处理登录问题 (用这种方式感觉有些复杂,还没太搞明白)

  1. springmvc.xml
    开启注解
    自动扫描根目录的设置
    各种bean的加载(数据库、redis、文件上传、dubbo等)
  2. DemoDao.xml
    参考中文官网
  3. jdbc.properites
    放在resource的一级目录下可自动加载,可在Spring中以${value}的形式读取数值
  4. log4j.properties
    log4j日志记录
    配置模板:
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
​
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
​
### set log levels - for more verbose logging change 'info' to 'debug' ###
​
log4j.rootLogger=debug, stdout
  1. freemarkerDemo.ftl
    freemarker使用场景:主要用于经常访问,但不怎么变化的页面(如物品详情页),在添加该商品时提前生成,减少数据库查询频率。
private void generateHtml(String templateName, String htmlPageName, Map dataMap) {
        Configuration configuration = freeMarkerConfigurer.getConfiguration();
        Writer writer = null;
        try {
            Template template = configuration.getTemplate(templateName);
            writer = new FileWriter(new File(outputpath+"\\"+htmlPageName));
            template.process(dataMap,writer);
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

3、从前端请求开始

axios.get axios.post是两种常用的请求方式,以json格式发送和接收输入,=>是ECMAScript6规范。以res接收服务端发过来的response,解析其中的res.data.data。后端配套Result类作为统一的返回数据类,规范交互。

created(){
            axios.post("/user/getUsername.do").then(
                res=>{
                    if (res.data.flag){
                        this.username = res.data.data;
                        axios.post("/user/getMenuList.do").then(
                            res => {
                                if (res.data.flag){
                                    this.menuList = res.data.data;
                                }
                            }
                        );
                    }
                })
        }

4、Controller

@RestController ----------Controller与Respondbody的集合体
@RequestMappping(“/user”)
@Reference(dubbo)
@Autowired
@RequestParameter(“id”) ------- 接收单个指定名称的字段
@RequestBody User ----------直接将前台传过来的json转为pojo对象

5、Service

@Service
@Transional 重点:注意事务的捕捉等级(rollbackFor = Exception.class)与异常抛出的等级(RuntimeException、 Exceptio)的对应关系。如下文注释部分。

@Service(interfaceClass = BankService.class)
@Transactional
public class BankServiceImpl implements BankService {

    @Autowired
    private BankDao bankDao;

    @Override
    public void transforMoney(String from, String to, int money) throws Exception{

        BankUser fromBankUser = bankDao.getBankUserByName(from);
        BankUser toBankUser = bankDao.getBankUserByName(to);

        Map map = new HashMap();
        map.clear();
        map.put("id", toBankUser.getId());
        map.put("money", toBankUser.getMoneycount() + money);
        bankDao.updateCount(map);


        if (fromBankUser.getMoneycount() - money < 0) {
            bankDao.mistake(1);
            //throw new Exception("余额不足");
            //注意Spring默认捕捉到RuntimeException和Error的错误才会rollback回退事务,
            //所以(1)(2)都行,但是(!3)无法回退事务
            //(1)@Transactional  与 throw new RuntimeException("余额不足");
            //(2)@Transactional(rollbackFor = Exception.class) 与  throw new Exception("余额不足");
            //(!3)@Transactional 与 throw new Exception("余额不足");
        }
        map.clear();
        map.put("id", fromBankUser.getId());
        map.put("money", fromBankUser.getMoneycount() - money);
        bankDao.updateCount(map);

    }
}

6、Dao

只写接口,对应在mybatis的xml文件中描述,main、resource路径是完全对应的,maven install后合并在同一路径下。

7、mybatis

xml文件
select --------(1)如果数据库字段名与pojo字段名不对应时使用 select member_id as “memberId” … 的方式insert --------(1)主键是由数据库自增的,可通过以下配置实现主键id的自返回

<insert id="add" parameterType="cn.cathayinfo.pojo.CheckGroup" useGeneratedKeys="true" keyProperty="id">
        insert into t_checkgroup (code,name,helpCode,sex,remark,attention)
        values (#{code},#{name},#{helpCode},#{sex},#{remark},#{attention})
    </insert>

parameterType 注意多个复杂参数时用map传进去
resultType -------- pojo时指定路径全称
resultMap ------------- 最复杂、多表联合查询,

<select id="findById" resultMap="findByIdResultMap">
  select * from t_setmeal  where id=#{id}
</select>
<resultMap type="pojo.Setmeal" id="baseResultMap">
  <id column="id" property="id"/>
  <result column="name" property="name"/>
  <result column="code" property="code"/>
  <result column="helpCode" property="helpCode"/>
  <result column="sex" property="sex"/>
  <result column="age" property="age"/>
  <result column="price" property="price"/>
  <result column="remark" property="remark"/>
  <result column="attention" property="attention"/>
  <result column="img" property="img"/>
</resultMap>
<resultMap type="pojo.Setmeal" 
           id="findByIdResultMap" 
           extends="baseResultMap">
  <collection property="checkGroups" 
              javaType="ArrayList"
              ofType="pojo.CheckGroup" 
              column="id"
              select="findCheckGroupById">
  </collection>
</resultMap>

8、utils公共类

DateUtils
POIUtils
QiniuUtilis
SMSUtilis
CalidateCode/Redis/Cookies

9、 分页查询 QueryPageBean / PageResult

@Override
    public PageResult pageQuery(QueryPageBean queryPageBean) {
        PageHelper.startPage(queryPageBean.getCurrentPage(), queryPageBean.getPageSize());
        Page<CheckGroup> checkGroups = checkGroupDao.selectByCondition(queryPageBean.getQueryString());
        return new PageResult(checkGroups.getTotal(), checkGroups);
    }

10、静态页面Freemarker用在经常访问但不经常变化的页面场景中

http://freemarker.foofun.cn/index.html

11、Reids

12、Echarts

<script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart1 = echarts.init(document.getElementById('chart1'));

        // 使用刚指定的配置项和数据显示图表。
        //myChart.setOption(option);

        axios.get("/report/getMemberReport.do").then((res)=>{
            myChart1.setOption(
                                {
                                    title: {
                                        text: '会员数量'
                                    },
                                    tooltip: {},
                                    legend: {
                                        data:['会员数量']
                                    },
                                    xAxis: {
                                        data: res.data.data.months
                                    },
                                    yAxis: {
                                        type:'value'
                                    },
                                    series: [{
                                        name: '会员数量',
                                        type: 'line',
                                        data: res.data.data.memberCount
                                    }]
                                });
        });
    </script>

13、认证、授权Spring Security

(1)基础表:User、Role、Permission、Menu 及 t_user_role、t_role_permission、t_role_menu。
请添加图片描述

(2)配置spring-security.xml文件,并引入到springmvc中;
(3)在web中配置权限filter;
(4) 实现@Component public class SpringSecurityUserService implements UserDetailsService
在这个类中实现上述表格的查询,根据用户user查询角色role,根据角色role查询可以看到哪些菜单Menu,根据角色role查询拥有哪些权限Permission。
(5)在每个方法上注解好权限要求

@PreAuthorize("hasAnyAuthority('CHECKITEM_QUERY')")
@RequestMapping("findAll")
public Result findAll() {
  try {
    List<CheckItem> checkItems =  checkItemService.findAll();
    return new Result(true, MessageConstant.QUERY_CHECKITEM_SUCCESS,checkItems);
   } catch (Exception ex) {
      return new Result(false, MessageConstant.QUERY_CHECKITEM_FAIL);
   }
 }

TODO:后期再找找看看有没有可视化的权限配置平台。现在使用的这个代码维护成本太高。

14、批处理任务Spring Schedule

引入Spring Schedule
cron表达式可从网上查,根据自己需求稍加修改即可
Spring Schedule的功能不够强大,单线程,处理简单问题还可,处理复杂耗时问题可能会产生死锁等待情况,可使用第三方更为强大的定时任务工具(如 Quartz Scheduler)。


    @Scheduled(cron = "0 0 12 * * ?")
    public void redisScheduledJob() {
        System.out.println("执行Redis清理缓存定时任务");
        Set<String> diff = jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES, RedisConstant.SETMEAL_PIC_DB_RESOURCES);
        if (diff != null && diff.size() > 0) {
            for (String fileName : diff) {
                QiniuUtils.deleteFromQiniu(fileName);
                jedisPool.getResource().srem(RedisConstant.SETMEAL_PIC_RESOURCES, fileName);
            }
        }
    }

参考资料

  1. java doc : https://docs.oracle.com/javase/8/docs/api/
  2. Spring:https://springdoc.cn/spring/index.html
  3. Spring MVC:https://springdoc.cn/spring/web.html#spring-web
  4. mybatis:https://mybatis.org/mybatis-3/zh_CN/configuration.html
  5. maven:https://maven.apache.org/pom.html
  6. freemarker:http://freemarker.foofun.cn/index.html
  7. echarts:https://echarts.apache.org/examples/zh/index.html
  8. axios:http://www.axios-js.com/zh-cn/docs/

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值